Data skew happens when a disproportionate number of child records point to a single parent, or when one user owns tens of thousands of records that Salesforce's sharing engine has to evaluate. Most test data generators produce evenly distributed records instead, which means the exact scenario that causes production outages never shows up in QA. If your test data has no skew, your performance testing is measuring the wrong thing.

This matters more than most admins assume. Salesforce's sharing recalculation, rollup summary engine, and parallel Apex triggers all degrade non-linearly as skew increases, not gradually. A sandbox loaded with 50,000 nicely distributed Contact records will run fine. The same 50,000 records with 8,000 of them pointing to one Account will expose lock contention nobody saw coming.

What Data Skew Actually Breaks in Salesforce

Salesforce enforces org-wide defaults and sharing rules through a set of internal tables that recalculate whenever ownership or hierarchy changes. When one record has an unusually large number of related child records, or one user owns an outsized share of records, those recalculation jobs slow down disproportionately. This is not a theoretical edge case. It is the single most common cause of "why did this org suddenly get slow" tickets on large implementations.

Three flavors show up repeatedly. Account data skew is more than 10,000 child records under one Account. Ownership skew is more than 10,000 records owned by one user, often an integration user or a queue. Lookup skew is heavy concurrent write activity against a single parent record referenced by a custom lookup field, which triggers row locking during bulk updates.

None of these are visible in a schema diagram. They only show up when you look at the actual distribution of foreign key values across your data, which is exactly what standard test data tools skip.

Why Uniform Random Data Hides the Problem

Most generation approaches assign parent records to child records using a flat random distribution: pick an Account ID at random for each Contact, pick a User ID at random for each Opportunity. Mathematically this spreads volume evenly. Statistically it is almost the opposite of how real Salesforce orgs behave.

Production data is never flat. A handful of house accounts absorb walk-in leads. A handful of power users get assigned the bulk of inbound cases because they close them fastest. Integration users end up owning millions of records from nightly sync jobs because nobody set up a proper queue. These patterns are ugly, unintentional, and completely typical, and they are precisely what breaks sharing recalculation under load.

If your test data generator spreads 100,000 Opportunities evenly across 500 Accounts, every parent gets roughly 200 children. Clean, tidy, useless. Real orgs concentrate volume: a few accounts get thousands of records while most get a handful. Testing against the tidy version tells you nothing about what happens when the ugly version hits production.

Modeling Skew with Weighted Distribution, Not Random Assignment

Building realistic skew means assigning a weight curve to parent selection instead of a uniform random pick. A Pareto-style distribution, where roughly 20% of parent records absorb 80% of child volume, gets you close to what most production orgs actually look like without needing a data science team to calibrate it.

SproutEzee handles this by reading the org's actual schema through the Metadata API and letting you define skew profiles per relationship: pick a parent pool size, a concentration percentage, and let the generator do weighted assignment during the Bulk API v2 load. You are not hand-writing thousands of explicit foreign key mappings. You are describing the shape of the distribution and letting the engine populate it at volume.

The practical difference matters. Hand-crafting 500 skewed records in a spreadsheet is tedious but doable. Hand-crafting the same skew pattern across 2 million records for a load test is not something anyone should attempt manually, and it is exactly the kind of job Bulk API v2 batching exists to handle once the distribution logic is defined upfront.

Testing Sharing Recalculation and Rollups Under Realistic Skew

Once skewed data exists in a sandbox, the actual test is watching what happens during operations that trigger recalculation: mass ownership transfers, territory reassignment, sharing rule changes, and rollup summary updates on the skewed parent.

A few checks worth running every time:

These tests are cheap to run once the data exists. The expensive part, historically, has been generating data with the right shape in the first place. That is the gap skew-aware generation closes.

Ownership Skew Deserves Its Own Test Pass

Account and lookup skew get most of the attention in Salesforce architecture guides, but ownership skew is the one I see teams underestimate most often. It creeps in quietly: an integration user gets created for a middleware sync, nobody assigns a proper queue, and eighteen months later that user owns 40% of the Case object.

Test for it by deliberately assigning a disproportionate share of generated records to a small number of synthetic "integration" or "automation" user records during data generation, then running the same sharing recalculation checks against that scenario. If your org-wide default for the object is Private or Public Read Only, this is where you will find the recalculation cost hiding.

The fix is usually architectural, not something test data alone solves. But you cannot make the architectural case to move an integration user's records into a queue without evidence that the current pattern is actually slow. Skewed test data is how you get that evidence before a customer does.

A Practical Skew-Testing Checklist

Before signing off on a performance test cycle, confirm the test data actually contains the failure modes you are trying to catch. A short checklist beats a long conversation:

If the answer to any of these is no, the performance test is measuring an org that does not resemble production. That is a wasted sprint. Skew-aware generation is not an optional refinement on top of schema-compliant test data. For any org planning sharing model changes, mass data operations, or growth past a few million records on a core object, it is the difference between a test result you can trust and one that just feels reassuring.

Frequently Asked Questions

What is data skew in Salesforce and why does it matter for testing?

Data skew is an uneven distribution of records, most commonly too many child records under one parent, or too many records owned by one user. It matters because Salesforce's sharing recalculation and rollup engines slow down disproportionately as skew increases, not gradually, so a test data set without skew will not reveal the same performance problems production data does.

How many child records count as account data skew?

Salesforce generally flags account data skew once a single Account has more than 10,000 related child records on an object with a private or controlled-by-parent sharing model. The exact threshold where problems appear varies by object and org configuration, but 10,000 is the widely cited planning number architects use.

Can standard random test data generators produce realistic skew?

No, most generators assign parent-child relationships using flat random distribution, which spreads volume evenly and produces data that looks nothing like a real production org. Realistic skew requires weighted assignment logic, typically a Pareto-style curve, that deliberately concentrates a large share of child records onto a small subset of parents.

How does ownership skew differ from account data skew?

Account data skew concerns child records concentrated under one parent record, while ownership skew concerns records concentrated under one user or queue owner. Ownership skew is especially common with integration users that accumulate records from automated syncs without ever being moved into a proper queue, and it triggers the same sharing recalculation slowdowns.

Does Bulk API v2 handle skewed data loads any differently than normal loads?

Bulk API v2 itself does not distinguish skewed from uniform data, but concurrent loads against a heavily skewed lookup target are far more likely to hit row-lock contention errors during processing. Structuring batches to serialize writes against known high-concentration parent records reduces lock failures during skewed data loads.