Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
DictionaryGGovernor Limits
DevelopmentAdvanced

Governor Limits

Governor Limits are the per-transaction caps that Salesforce enforces on every Apex execution, every SOQL query, every DML statement, every callout, and every heap allocation.

§ 01

Definition

Governor Limits are the per-transaction caps that Salesforce enforces on every Apex execution, every SOQL query, every DML statement, every callout, and every heap allocation. They exist because Salesforce is a multitenant platform: one organization''s code runs on the same hardware as every other organization''s code, and unrestricted resource use by one tenant would degrade performance for all the others. Governor Limits enforce a hard ceiling so no single transaction can take more than its share.

Every Apex transaction is bounded by a set of synchronous and asynchronous caps. Common synchronous limits include 100 SOQL queries, 150 DML statements, 50,000 records returned by SOQL, 10,000 records modified by DML, 10 seconds of CPU time, 6 MB of heap, and 100 callouts. Asynchronous transactions (Queueable, Future, Batch) get higher caps on most of these. Hitting a limit throws an uncatchable Apex exception; the entire transaction rolls back. Defensive design (bulkification, async patterns, selective queries) is mandatory in any production Apex codebase.

§ 02

The caps every Salesforce developer hits before they learn them

Why governor limits exist

Salesforce hosts thousands of customer orgs on shared infrastructure. Without limits, one organization writing an unbounded loop would consume CPU, RAM, or database I/O proportional to their data volume, starving every other tenant on the same pod. Governor Limits are the platform''s answer: per-transaction caps that guarantee fair use. They are intentionally low; the design philosophy is that bulk-safe, set-based code stays well under the limits without effort, and only buggy or unbulkified code hits them.

Synchronous vs. asynchronous limits

The standard synchronous limits apply to triggers, anonymous Apex, Visualforce controllers, and most user-driven transactions. Asynchronous Apex (Queueable, @future, Batchable, Schedulable) gets higher limits because the platform can spread the work across more time and processes. SOQL is 100/200 sync/async, DML is 150/150, callouts are 100/100, CPU time is 10s/60s, heap is 6MB/12MB. Knowing which set applies is the first step to designing around the caps.

Bulkification patterns

The single highest-leverage pattern is bulkification: write code that handles many records in one transaction without scaling the number of SOQL or DML statements linearly. Get records once, build a Map keyed by record ID, loop over the input collection assigning values from the Map, then a single DML at the end. Two SOQL and one DML regardless of whether the trigger fires on one record or 200. Most governor-limit failures come from for-loops with DML or SOQL inside them.

SOQL selectivity and the 50,000-record limit

Apex throws a CPU or row-limit exception when a SOQL query returns more than 50,000 rows or scans more than the indexed-rows threshold. The fix is selective filtering: WHERE clauses on indexed fields (Id, Name, External ID, custom indexes) keep the scan small. For data volumes above 50,000 records, switch to Batchable Apex, which processes 200 records at a time in separate transactions, each with its own governor budget.

CPU time and heap

Synchronous Apex gets 10 seconds of CPU time and 6 MB of heap. CPU time is wall-clock execution of Apex code, excluding callout wait time. Heap is the total memory of in-Apex variables and SOQL result sets. Loading a 50,000-record query result with 20 fields per record uses several megabytes and can hit the heap limit even before any logic runs. Use LIMIT clauses, select only needed fields, and free large variables (set them to null) when they are no longer needed.

Callout limits and timing

Each transaction can make 100 outbound callouts, each up to 120 seconds. The sum of all callout time counts against the transaction budget; a transaction with three callouts at 30 seconds each consumes 90 seconds of wall clock, even though the CPU itself was idle. Apex callouts cannot be made after DML in the same transaction (uncommitted-work-pending exception). The fix is to make callouts first, then DML, or to move DML to async via @future or Queueable.

Recursion, triggers, and limit accumulation

Limits are per-transaction, not per-trigger. A record-triggered flow that updates the same record causes the trigger to re-fire; each re-firing accumulates against the same transaction budget. Bad recursion can burn through 100 SOQL queries in milliseconds. Use static recursion guards in Apex triggers (a static Set tracking processed record IDs) and ISCHANGED() in flows to break the cycle.

§ 03

Design Apex code that stays under governor limits

The discipline is the same across triggers, controllers, and batch jobs. Bulkify, query selectively, run async when the work is heavy, and instrument the limits in production code.

  1. Bulkify every loop

    Never put SOQL or DML inside a for-loop. Collect record IDs in a Set, query once, build a Map, loop over the input, single DML at the end.

  2. Selective-filter every query

    WHERE clauses on indexed fields (Id, External ID, custom-indexed lookup) keep the scan inside the selectivity threshold. Avoid LIKE on non-indexed text fields.

  3. Move heavy work to async

    Batchable Apex for data volumes above 50,000 records. Queueable for chained transactional work. @future for fire-and-forget callouts. Each async context gets its own governor budget.

  4. Instrument Limits class

    Use Limits.getQueries(), Limits.getDMLStatements(), Limits.getCpuTime() in logging. Surface near-limit warnings (e.g., 80 percent of CPU) to a logging framework so you see problems before they become exceptions.

  5. Test with bulk data

    Apex tests must insert at least 200 records (or call the method with 200 records in a list) to exercise bulk paths. Test methods that only insert one record do not detect limit failures that hit at scale.

Gotchas
  • Governor limits cannot be increased per-org. Salesforce Support cannot raise them. Designing around them is the only path.
  • Limit exceptions are uncatchable; they bypass try-catch and roll back the entire transaction. Defensive code must avoid hitting them, not handle them.
  • Test methods run in a separate context with their own governor budget. Passing in test does not guarantee passing in production at higher scale.
  • Flow elements count against the same SOQL and DML governor limits as Apex. A record-triggered flow with unbulkified DML hits the 150 cap as fast as bad Apex.
§

Trust & references

Sources

Cross-checked against the following references.

Official documentation

Straight from the source - Salesforce's reference material on Governor Limits.

Keep learning

Hands-on resources to go deeper on Governor Limits.

Was this entry helpful?
Help us write better definitions. Quick reactions or detailed edit suggestions.

About the Author

Dipojjal Chakrabarti is a B2C Solution Architect with 29 Salesforce certifications and over 13 years in the Salesforce ecosystem. He runs salesforcedictionary.com to help admins, developers, architects, and cert/interview candidates sharpen their fundamentals. More about Dipojjal.

§

Test your knowledge

Q1. What is required before deploying Governor Limits-related code to production?

Q2. What skill set is typically needed to work with Governor Limits?

Q3. Where would a developer typically work with Governor Limits?

§

Discussion

Loading…

Loading discussion…