The single cause

Nearly every governor limit failure traces to one pattern: a database query or update inside a loop. Code that processes one record at a time works in testing and fails the moment a data load sends two hundred. Fixing that pattern prevents most of the class.

Written for technical managers who keep hearing "governor limits" as an explanation for failures and want to understand what is actually happening.

What governor limits are

Salesforce runs many organisations on shared infrastructure. To stop any one org consuming resources that would affect others, it caps what a single transaction can do.

ResourceWhy it is cappedWhat exceeding it means
Database queries per transactionQuery load affects shared infrastructureTransaction fails outright
Records retrievedMemory consumptionTransaction fails
Database operations per transactionWrite loadTransaction fails
CPU timeProcessing capacityTransaction fails
Heap sizeMemory per transactionTransaction fails
Callouts to external systemsExternal dependency riskTransaction fails

The important detail: these are per transaction, not per record. A trigger firing on a two-hundred-record update runs once, for all two hundred — and must complete within a single transaction's allowance.

Why code passes testing and fails in production

The gap is testing with one record. A developer saves a record, the trigger fires, everything works. In production, a data import or an integration updates two hundred records at once. The same trigger now needs two hundred times the queries — and fails. The code was never wrong for one record; it was written as though one record were the only case.

The pattern that causes it

Without going deep into code, the shape is recognisable even to non-developers:

The failing pattern

  • For each record that changed…
  • …query the database for related data
  • …then update something
  • 200 records = 200 queries + 200 updates
  • Fails well before that

The bulk pattern

  • Collect all the IDs first
  • Query once for all related data
  • Process in memory
  • Update once, as a batch
  • 200 records = 1 query + 1 update

The bulk pattern is not an optimisation. It is the correct way to write Salesforce code, and it costs no more to write than the failing version.

How to tell whether your org is at risk

  1. Run a bulk test in a sandbox — update two hundred records at once and watch for failures.
  2. Ask whether any Apex has queries inside loops. A developer can answer this in an hour; it is the highest-value question.
  3. Check what happens on data import. Historic failures during imports are a strong signal.
  4. Review integration behaviour — external systems frequently send batches.
  5. Look at test coverage quality. Tests that only ever create one record prove nothing about bulk behaviour.

The most informative question to ask a Salesforce developer: "do your tests create two hundred records?" Tests that insert one record pass regardless of whether the code is bulk-safe. Tests that insert a full batch are the only ones that prove anything about production behaviour.

Other common causes

  • Trigger cascades — one trigger updating records that fire another trigger, compounding within the same transaction.
  • Recursive triggers — a trigger updating the same object it fires on, re-entering itself.
  • Flows and Apex combined — both consuming the same transaction allowance without either being aware.
  • Callouts in loops — external API calls per record, which fails very quickly.
  • Unfiltered queries — retrieving far more records than needed.

What remediation involves

  1. Identify the failing paths with bulk testing in a sandbox.
  2. Restructure to bulk patterns — collect, query once, process, update once.
  3. Consolidate triggers — one per object with a handler class, rather than several competing.
  4. Move callouts out of the transaction — queue them for asynchronous processing.
  5. Write bulk tests so the fix cannot regress.
  6. Re-test with production-scale data.

The cost of leaving it

Intermittent, hard-to-reproduce failures are the worst kind of technical debt — they erode confidence in the platform, make every data operation risky, and typically get worse as data volumes grow. Remediation is a defined piece of work; living with it is an indefinite tax.

Seeing failures on data loads or integrations? Tell us when they occur — the pattern is usually identifiable quickly. See our Salesforce service, auditing an inherited org, and Apex vs Flow.

Frequently asked questions

Because it is multi-tenant — your org shares infrastructure with many others. Limits prevent any one tenant consuming resources that affect everyone else. They are a feature of the architecture, not an arbitrary restriction, which is why they cannot be raised on request.
Some limits are adjustable through Salesforce support for specific circumstances, but the core per-transaction limits are not. Designing within them is the only reliable approach — and code written properly rarely comes close to them.
Run a bulk operation in a sandbox with production-scale data. Code that fails there will fail in production. Also check whether any Apex contains SOQL or DML inside a loop — that single pattern causes most limit failures.