Skip to main content

SF-0017 · Concept · Medium

What are governor limits?

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

Governor limits are the runtime quotas Salesforce enforces on every Apex transaction. They exist because Salesforce is multi-tenant — your code shares CPU, memory, and database connections with thousands of other customers on the same instance. Without hard caps, one runaway loop could starve every other org on the pod.

The limits are per-transaction, not per-day. A transaction is everything that runs from the moment your trigger or controller fires until it returns — including DML, callouts, and chained logic. Cross a limit, and the runtime throws a System.LimitException and rolls the entire transaction back.

The core per-transaction limits

Here are the limits a Salesforce developer is expected to know cold (synchronous, current as of Spring ‘26):

ResourceSynchronous limitAsync (batch/queueable/future)
SOQL queries100200
Records retrieved by SOQL50,00050,000
SOSL queries2020
DML statements150150
Records processed by DML10,00010,000
CPU time10,000 ms60,000 ms
Heap size6 MB12 MB
Callouts100100
Callout timeout (cumulative)120 seconds120 seconds
@future calls500 (can’t chain)
Queueable jobs501 (chained)

A few are easy to miss:

  • CPU time is Apex CPU only — time spent in your code, not waiting on SOQL or callouts. Aggregations, sorts, and large Map walks burn it fast.
  • Heap is the live size of every variable in memory. Building a List<sObject> of 50,000 records will not blow SOQL row limits but very likely will blow heap.
  • DML rows counts each saved record, not each insert statement. One insert of 10,001 records fails.

Why async gets relaxed limits

Async transactions (batch, queueable, scheduled, future) run on a different worker pool. They’re allowed longer CPU and more SOQL queries because no user is waiting on a page response. The trade-off: they have their own concurrency caps (e.g., 5 concurrent batch jobs per org) and the platform schedules them when it has capacity.

How to stay under

  1. Bulkify — never SOQL or DML inside a for loop. The platform fires triggers on batches of up to 200 records and bulk APIs push the same code through hundreds of thousands.
  2. SOQL for-loops over Listfor (Account a : [SELECT ... FROM Account]) streams 200 rows at a time so heap stays small.
  3. Aggregate on the serverSELECT COUNT(Id), SUM(Amount) FROM Opportunity runs in the database, not on your CPU budget.
  4. Defer to async — long callouts, multi-million-row scans, or anything risking CPU belongs in Database.Batchable or Queueable.
  5. Inspect at runtimeLimits.getQueries(), Limits.getCpuTime(), Limits.getHeapSize() return the running totals so you can defensive-check before a risky operation.

What interviewers are really looking for

The basic answer names a few limits. The senior answer explains why they exist (multi-tenancy), names the resource categories (SOQL/DML/CPU/heap/callouts), distinguishes sync vs async budgets, and connects them to patterns — bulkification, SOQL aggregation, async deferral. Mention Limits.getQueries() for runtime introspection and you’ve signaled production-debug experience.

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