Governor Limits and Apex Transactions
Governor Limits and Apex Transactions are fundamental concepts in Salesforce development that every Platform Developer I must understand. **Apex Transactions:** An Apex transaction represents a set of operations executed as a single unit of work. A transaction begins when a trigger, web service ca… Governor Limits and Apex Transactions are fundamental concepts in Salesforce development that every Platform Developer I must understand. **Apex Transactions:** An Apex transaction represents a set of operations executed as a single unit of work. A transaction begins when a trigger, web service call, Visualforce page request, or anonymous block is initiated. All DML operations, SOQL queries, and processing within that execution context are part of the same transaction. If any operation fails, the entire transaction is rolled back, ensuring data integrity. Transactions follow an all-or-nothing principle unless savepoints are used for partial rollbacks. **Governor Limits:** Salesforce operates on a multi-tenant architecture where resources are shared among all organizations. Governor Limits are runtime restrictions enforced by the platform to prevent any single tenant from monopolizing shared resources. These limits are applied per transaction and ensure fair usage. **Key Governor Limits include:** - **SOQL Queries:** 100 per synchronous transaction, 200 per asynchronous - **DML Statements:** 150 per transaction - **DML Rows:** 10,000 per transaction - **SOQL Query Rows Retrieved:** 50,000 per transaction - **Heap Size:** 6 MB (synchronous), 12 MB (asynchronous) - **CPU Time:** 10,000 ms (synchronous), 60,000 ms (asynchronous) - **Callouts:** 100 per transaction - **Future Methods:** 50 per transaction **Best Practices to Avoid Hitting Limits:** 1. **Bulkify code** — Never write SOQL or DML inside loops 2. Use **collections** (Lists, Maps, Sets) to process records efficiently 3. Use **SOQL FOR loops** for large data sets 4. Leverage **asynchronous processing** (Batch Apex, Queueable, Future methods) for heavy operations 5. Use **Limits class** methods like `Limits.getQueries()` to monitor consumption at runtime Violating governor limits throws a runtime `LimitException` that cannot be caught, causing the entire transaction to fail. Understanding these limits is critical for writing scalable, efficient Apex code on the Salesforce platform.
Governor Limits and Apex Transactions – Salesforce Platform Developer 1 Exam Guide
Governor Limits and Apex Transactions
Why Is This Topic Important?
Governor limits are one of the most critical concepts on the Salesforce Platform Developer 1 exam. Salesforce operates in a multi-tenant environment, meaning many organizations share the same physical resources (CPU, memory, database). To ensure no single tenant monopolizes these shared resources, Salesforce enforces strict runtime limits known as governor limits. As a developer, understanding these limits is essential because:
• They directly shape how you write and architect Apex code.
• Violating them causes unrecoverable runtime exceptions that cannot be caught.
• Nearly every real-world Salesforce development task requires awareness of these constraints.
• Questions about governor limits appear frequently on the exam, often embedded in scenario-based questions about triggers, batch jobs, and integrations.
What Are Governor Limits?
Governor limits are runtime enforcement thresholds that Salesforce places on Apex code execution within a single transaction. A transaction is a set of operations that execute as a single unit of work. If any governor limit is exceeded during a transaction, the entire transaction is rolled back and an unhandled System.LimitException is thrown.
Key governor limits you must know include:
• SOQL Queries: 100 SOQL queries per synchronous transaction; 200 per asynchronous transaction.
• SOSL Searches: 20 SOSL queries per transaction.
• DML Statements: 150 DML statements per transaction.
• DML Rows: 10,000 rows processed by DML statements per transaction.
• SOQL Query Rows: 50,000 rows retrieved by SOQL queries per transaction.
• Heap Size: 6 MB for synchronous; 12 MB for asynchronous transactions.
• CPU Time: 10,000 milliseconds (10 seconds) for synchronous; 60,000 milliseconds (60 seconds) for asynchronous transactions.
• Callouts: 100 callouts per transaction; each callout has a maximum timeout of 120 seconds, with a total callout time limit of 120 seconds.
• Future Methods: 50 future method invocations per transaction.
• Queueable Jobs: 50 jobs added with System.enqueueJob per transaction.
• Total Email Invocations: 10 sendEmail method invocations per transaction.
What Is an Apex Transaction?
An Apex transaction represents the entire sequence of operations that occurs from the beginning of a request to the end. All work within a transaction either succeeds completely or is rolled back entirely. Common triggers of a transaction include:
• A trigger firing due to a DML operation.
• An Apex REST or SOAP web service call.
• A Visualforce page action or Lightning controller method.
• An anonymous Apex execution.
• A Batch Apex execute method invocation (each batch chunk is its own transaction).
• A Queueable Apex execute method.
• A Scheduled Apex execute method.
Important: All triggers that fire from the same initial DML operation share the same transaction context and therefore share the same governor limits. For example, if an insert on Account fires Trigger A (which performs 80 SOQL queries) and then cascading logic fires Trigger B (which performs 25 SOQL queries), the total is 105, which exceeds the 100-query synchronous limit and causes a LimitException.
How Governor Limits Work in Practice
1. Bulkification
The number one best practice to avoid hitting governor limits is to bulkify your code. This means writing code that efficiently handles 1 record or 200 records (the default trigger batch size) without increasing the number of SOQL queries, DML statements, or other limited operations.
Bad pattern (SOQL inside a loop):
for (Account acc : Trigger.new) {
Contact[] contacts = [SELECT Id FROM Contact WHERE AccountId = :acc.Id]; // SOQL inside loop!
}
Good pattern (bulkified):
Map<Id, List<Contact>> contactsByAccount = new Map<Id, List<Contact>>();
for (Contact c : [SELECT Id, AccountId FROM Contact WHERE AccountId IN :Trigger.newMap.keySet()]) {
// Build map
}
2. Avoid DML Inside Loops
Collect records in a list and perform a single DML operation outside the loop.
3. Use Collections
Use Maps, Sets, and Lists to aggregate data and reduce redundant queries.
4. Use the Limits Class
Salesforce provides the Limits class with methods like:
• Limits.getQueries() – returns the number of SOQL queries used so far.
• Limits.getLimitQueries() – returns the maximum allowed SOQL queries.
• Limits.getDMLStatements() and Limits.getLimitDMLStatements()
• Limits.getHeapSize() and Limits.getLimitHeapSize()
• Limits.getCpuTime() and Limits.getLimitCpuTime()
These methods are useful for debugging and for writing defensive code.
5. Leverage Asynchronous Apex
When you anticipate large data volumes or complex processing, use asynchronous patterns:
• Batch Apex – processes records in chunks; each execute method invocation gets its own transaction with fresh governor limits.
• Queueable Apex – allows chaining jobs and has higher limits (asynchronous).
• Future Methods – simple asynchronous processing with higher heap and query limits.
• Platform Events – publishing events can decouple processing into separate transactions.
6. Savepoints and Partial Rollbacks
You can use Database.setSavepoint() and Database.rollback(sp) to roll back part of a transaction. However, each savepoint counts toward governor limits. Setting a savepoint and rolling back does not reset the governor limit counters — the SOQL queries and DML statements already consumed still count.
7. Order of Execution
Understanding Salesforce's order of execution is essential because multiple automations (before triggers, after triggers, workflow rules, process builders, flows, validation rules) all execute within the same transaction. Their cumulative resource consumption counts toward the same set of governor limits.
Synchronous vs. Asynchronous Limits Summary
| Limit | Synchronous | Asynchronous |
SOQL Queries: 100 (sync) / 200 (async)
Heap Size: 6 MB (sync) / 12 MB (async)
CPU Time: 10,000 ms (sync) / 60,000 ms (async)
DML Statements: 150 (both)
DML Rows: 10,000 (both)
SOQL Query Rows: 50,000 (both)
Common Scenarios That Cause Governor Limit Issues
• SOQL in a for loop inside a trigger: Easily exceeds the 100-query limit when processing bulk records.
• Recursive triggers: Trigger A updates records that fire Trigger B, which updates records that fire Trigger A again — rapidly consuming limits.
• Large query results without filtering: Retrieving too many rows can exceed the 50,000 row limit.
• Multiple automations on the same object: Triggers + Process Builder + Flows all share the same transaction limits.
• Callouts inside loops: Exceeding the 100-callout limit or the total timeout.
Handling LimitException
A System.LimitException cannot be caught by try-catch blocks. This is a deliberate design decision by Salesforce. The only remedy is to write code that stays within limits. You should use the Limits class proactively rather than relying on exception handling.
Exam Tips: Answering Questions on Governor Limits and Apex Transactions
Tip 1: Memorize the key numbers.
You must know: 100 SOQL (sync), 200 SOQL (async), 150 DML statements, 10,000 DML rows, 50,000 query rows, 6 MB heap (sync), 12 MB heap (async), 100 callouts, 50 future calls, and 10,000 ms CPU (sync). These numbers appear directly and indirectly in many questions.
Tip 2: Look for SOQL or DML inside loops.
When a question presents a code snippet, immediately scan for any query or DML operation inside a for loop. This is the most commonly tested anti-pattern. The correct answer will almost always involve moving the operation outside the loop using collections.
Tip 3: Understand transaction boundaries.
If a question asks about governor limits in the context of Batch Apex, remember that each execute invocation is a separate transaction with fresh limits. The start method is one transaction, each execute is another, and finish is yet another.
Tip 4: Remember that all triggers on the same object share one transaction.
If a question describes multiple triggers on the same object, their SOQL and DML counts are cumulative within the same transaction.
Tip 5: Know that LimitException cannot be caught.
If a question asks how to handle a LimitException, the answer is never a try-catch block. The answer involves writing bulkified code or using asynchronous processing to stay within limits.
Tip 6: Identify when asynchronous processing is the solution.
If a scenario describes processing millions of records or making many callouts, the answer typically involves Batch Apex, Queueable Apex, or Future methods. Batch Apex is especially suited for large data volumes because each chunk gets its own governor limits.
Tip 7: Watch for the Limits class in answer choices.
Questions may ask how to programmatically check remaining limits. The answer involves Limits.getQueries(), Limits.getLimitQueries(), etc. Be familiar with the naming pattern: get[LimitName]() for current usage and getLimit[LimitName]() for the maximum.
Tip 8: Distinguish per-transaction vs. per-organization limits.
Most exam questions focus on per-transaction limits. However, be aware that some limits are per-organization (e.g., the total number of asynchronous Apex executions in a 24-hour period is 250,000 or the number of licenses × 200, whichever is greater).
Tip 9: Savepoints do not reset limit counters.
If a question asks whether rolling back to a savepoint resets governor limit consumption, the answer is no. The DML and SOQL counts remain.
Tip 10: Read scenario questions carefully for cascading effects.
Many exam questions describe a chain of operations: an insert triggers an after-insert trigger, which performs an update, which fires another trigger, which fires a workflow, etc. Trace through the entire chain and add up the operations to determine if a limit will be exceeded.
Tip 11: Know the difference between Database methods and standard DML.
Database.insert(records, false) allows partial success and does not throw an exception for individual failures, but it still counts as one DML statement. This does not help with governor limits on the number of DML statements — it helps with error handling. Don't confuse the two concepts.
Tip 12: Platform Events as a limit management strategy.
Publishing a platform event and having a trigger on that event run in a separate transaction is a valid strategy for managing governor limits. Be aware that this is increasingly tested.
Quick Reference Summary for the Exam:
• SOQL queries: 100 sync / 200 async
• DML statements: 150
• DML rows: 10,000
• SOQL rows retrieved: 50,000
• Heap: 6 MB sync / 12 MB async
• CPU: 10,000 ms sync / 60,000 ms async
• Callouts: 100
• Future calls: 50
• Queueable jobs: 50
• LimitException: CANNOT be caught
• Savepoint rollback: Does NOT reset limit counters
• Batch Apex execute: Each chunk = new transaction = fresh limits
Mastering governor limits and understanding Apex transaction boundaries is fundamental to becoming a proficient Salesforce developer and is heavily tested on the Platform Developer 1 certification exam. Practice identifying anti-patterns, bulkifying code, and choosing the right asynchronous pattern for different scenarios.
🎓 Unlock Premium Access
Salesforce Certified Platform Developer I + ALL Certifications
- 🎓 Access to ALL Certifications: Study for any certification on our platform with one subscription
- 2750 Superior-grade Salesforce Certified Platform Developer I practice questions
- Unlimited practice tests across all certifications
- Detailed explanations for every question
- PD1: 5 full exams plus all other certification exams
- 100% Satisfaction Guaranteed: Full refund if unsatisfied
- Risk-Free: 7-day free trial with all premium features!