On this page

The honest list#

Most "governor limits" posts read like the docs. This one is what I actually keep in a sticky note on my second monitor.

SOQL — 100 sync, 200 async#

Still the most common limit teams trip. The mistake is rarely a single bad query — it's a trigger that calls a handler that calls a utility that lazy-loads a related record.

apex
// Bad — N+1 inside a loop
for (Opportunity o : opps) {
  Account a = [SELECT Id, Name FROM Account WHERE Id = :o.AccountId];
}

// Better — bulkified
Map<Id, Account> accts = new Map<Id, Account>(
  [SELECT Id, Name FROM Account WHERE Id IN :accountIds]
);

CPU time — 10,000ms sync#

The silent killer. You don't see CPU on a query plan; you see it in a 60-step Flow that runs Apex on each step.

Heap — 6 MB sync#

Easy to blow with String.valueOf(largeBlob) or holding a huge Map while you do work.

DML rows — 10,000#

Comes up in data loaders. Use Database.executeBatch and chain if you have to.

My rules of thumb#

  1. Never query inside a loop. Period.
  2. Selector classes for every SObject — one place to audit.
  3. If a transaction needs more than 50% of any limit, write a test that fails when it hits 80%.