Skip to main content

SF-0312 · Concept · Medium

What are some governor limits which are very frequently encountered in salesforce apex?

✓ Verified by Vikas Singhal · Last reviewed 5/17/2026 · Updated for Spring '26

Most Salesforce apex outages trace back to one of five limits. Knowing which they are — and which patterns hit them — is half the battle.

The “front five” you’ll meet in production

LimitSynchronous capTypical cause
SOQL queries per transaction100A SELECT inside a for loop on Trigger.new
DML statements per transaction150An update inside a loop, or per-record save
Total DML rows per transaction10,000Mass-update batch processed in a single transaction
Apex CPU time10,000 ms (10 s)Nested loops over large collections, heavy Map joins
Heap size6 MBHolding 50k SObjects in memory for processing

1. SOQL queries (101 / “too many SOQL queries”)

The classic bulkification failure:

// BAD — fires N queries when N accounts come through
for (Account a : Trigger.new) {
    a.Top_Contact__c = [SELECT Id FROM Contact
                        WHERE AccountId = :a.Id LIMIT 1].Id;
}

Fix: query once, map by parent ID, look up in the loop.

Map<Id, Contact> firstByAcct = new Map<Id, Contact>();
for (Contact c : [SELECT Id, AccountId FROM Contact
                  WHERE AccountId IN :Trigger.newMap.keySet()
                  ORDER BY CreatedDate]) {
    if (!firstByAcct.containsKey(c.AccountId)) {
        firstByAcct.put(c.AccountId, c);
    }
}
for (Account a : Trigger.new) {
    Contact c = firstByAcct.get(a.Id);
    if (c != null) a.Top_Contact__c = c.Id;
}

2. DML statements (151 / “too many DML statements”)

// BAD
for (Account a : accs) update a;

// GOOD
update accs;

Even when each call is small, the platform counts the statement, not the row count.

3. DML rows (10,001+ records)

Mass-data jobs that try to save more than 10,000 records in one transaction throw Too many DML rows. The fix is Batch Apex — each execute() call is its own transaction with its own budget.

4. CPU time exceeded

This one’s sneaky because there’s no single API call to blame. It accumulates from every operation in pure Apex (loops, string ops, JSON parse, sort, math).

Top causes:

  • Nested loops over Trigger.new × related records when a Map<Id, ...> lookup would do it in O(N)
  • Heavy JSON.deserialize of large payloads
  • Repeated instanceof / getDescribe calls

Diagnose with Limits.getCpuTime() printed at checkpoints.

5. Heap size

Storing tens of thousands of fat SObjects (long text fields, formulas) breaches 6 MB fast. The fix:

// Streams 200 rows at a time, garbage-collecting each batch
for (Account a : [SELECT Id, Name FROM Account WHERE Active__c = true]) {
    process(a);
}

A for loop over a SOQL query expression — not a pre-fetched List — keeps heap flat.

The “silent five” that hurt on integrations

LimitCapWhere it bites
Callouts per transaction100Loop calling an external API per record
Cumulative callout timeout120 sA single slow endpoint stacked many times
@future calls50Fire-and-forget per record in a trigger
Queueable depth (chained)5 (sync), unlimited (async)Recursive job chains
Email invocations10 (single), 10 (mass)Notification per record

What interviewers are really looking for

Knowing the numbers is table stakes. The signal is whether you can match each limit to the anti-pattern that triggers it — SELECT in a loop hits the 100 SOQL cap; per-record DML hits 150 statements; cross-joining Trigger.new against related records hits 10s CPU. Wrap up with bulkification, SOQL aggregation, and async deferral as the structural fixes.

Verified against: Apex Developer Guide — Execution Governors and Limits. Last reviewed 2026-05-17 for Spring ‘26 release.