What is Data Skew in Salesforce? Explanation, Examples & Mitigation

Understanding Data Skew

Data skew in Salesforce occurs when a large number of records are related to a single record (or a small set of records) in a way that creates an uneven distribution of data and processing load. This imbalance causes performance degradation, locking/contention issues, and sharing recalculation problems—especially during bulk operations, integrations, or mass updates.

Why Data Skew Matters

Salesforce is a multi-tenant platform optimized for balanced data distribution. When skew exists, several platform limits and behavior patterns (record locking, sharing recalculation, and selective indexing) can trigger, leading to slowed transactions, failed batches, and poor user experience.

Common Types of Data Skew

1) Ownership Skew

Ownership skew happens when many records (leads, cases, opportunities, custom objects) are owned by the same user. This leads to high contention on that user’s ownership-based sharing and can create lock contention during inserts/updates/deletes.

2) Lookup Skew

Lookup skew occurs when thousands (or more) of child records reference the same parent via a lookup field. This affects roll-up operations, sharing calculations, and can cause hot-spotting on the parent record during updates.

3) Master-Detail / Sharing Recalculation Skew

When a parent record is updated and numerous child records exist, Salesforce recalculates sharing and role hierarchy implications. Large fan-outs cause lengthy recalculation and may hit CPU/time limits or queueing delays.

Typical Symptoms

Look for these signs to identify data skew:

– Increased record locking errors (e.g., “UNABLE_TO_LOCK_ROW”) during bulk operations.

– Slow bulk data loads or failed data loads with timeouts.

– Longer Apex transaction times or governor-limit exceptions during mass updates.

– Unexpected sharing recalculation jobs or long-running sharing queue processes.

Real-world Example

Imagine a single Account record with 100,000 related custom child records via a lookup. Attempting to update those child records in bulk (through Apex, Data Loader, or an integration) can cause “unable to lock row” errors and very slow processing because the platform locks the parent or related sharing rows.

How to Detect Data Skew

– Use SOQL to count children per parent. For example:

SELECT ParentId, COUNT(Id) FROM ChildObject__c GROUP BY ParentId HAVING COUNT(Id) > 1000

– Review Apex job failures and Data Loader error logs for lock-related messages.

– Use Salesforce debug logs and the Apex Jobs / AsyncApexJob list to inspect long-running processes or repeated sharing recalculation jobs.

Mitigation Strategies

1) Distribute Ownership

Spread record ownership across multiple users or a queue where possible. Avoid assigning massive numbers of records to a single user.

2) Reduce Fan-out

Where feasible, limit the number of child records per parent. Archive or partition old records, or split parent records logically to reduce references.

3) Batch Operations Carefully

Use smaller batches when processing updates (e.g., 100–200 records) to reduce lock contention. Implement retry logic for transient locking errors.

4) Use Asynchronous Patterns

Move heavy processing to asynchronous queues (Batch Apex, Queueable, or Platform Events) and schedule operations during off-peak hours.

5) Avoid Hot-Spot Updates on Parent Records

If child updates don’t require touching the parent, avoid updating parent fields. For roll-ups, consider declarative tools (Roll-Up Summary fields) or asynchronous roll-ups that don’t lock the parent for each child change.

6) Selective Indexing & Query Optimization

Ensure queries are selective and proper indexes exist for large datasets. Non-selective queries on skewed data will lead to full scans and timeouts.

7) Re-architecture Where Needed

In cases of extreme skew, consider modeling changes: use junction objects, aggregate parent records, or move seldom-accessed child records to a separate object or external store.

Quick Apex Pattern for Retry on Locking

Implement simple retry logic around DML to handle transient locking:

Integer retries = 3;
while (retries-- > 0) {
try {
update records;
break;
} catch (DmlException e) {
if (!e.getMessage().contains('UNABLE_TO_LOCK_ROW') || retries == 0) throw e;
// small sleep or backoff (only in async contexts)
}
}

Conclusion

Data skew is a common cause of performance and stability problems in Salesforce orgs with large data volumes or concentrated ownership/relationships. Detect it proactively with queries and logs, and mitigate it through better data modeling, distribution, batching, and asynchronous processing.