Governor Limits in Salesforce: What They Are and How to Handle Them
Salesforce is a multi-tenant platform, meaning many customers share the same infrastructure. To ensure fair usage and system stability, Salesforce enforces something called Governor Limits.
If you’re developing on Salesforce and haven’t run into these limits yet, you will—so it’s essential to understand what they are and how to design your code and automation to stay within them.
What Are Governor Limits?
Governor Limits are runtime limits enforced by the Salesforce platform to ensure that no single customer monopolizes shared resources. These limits apply to everything from SOQL queries and DML operations, to heap size, API calls, and more.
Think of governor limits as “rules of the road” for developers—keeping everyone safe and efficient.
Common Governor Limits (with Values)
Here are some of the most commonly hit limits:
Limit Type | Synchronous | Asynchronous |
Total SOQL Queries | 100 | 200 |
DML Statements (insert/update) | 150 | 150 |
Records Retrieved by SOQL | 50,000 | 50,000 |
Records Processed by DML | 10,000 | 10,000 |
CPU Time | 10,000 ms | 60,000 ms |
Heap Size | 6 MB | 12 MB |
Callouts per transaction | 100 | 100 |
Future Methods per transaction | 50 | – |
Queueable Jobs Chain Depth | 1 (start) + 1 (enqueue another) |
Why Do Governor Limits Matter?
Because exceeding a governor limit causes the entire transaction to fail—with no partial success.
Example:
If your trigger hits the 101st SOQL query, it will throw a “Too many SOQL queries: 101” error and roll back the entire operation.
Real-World Example
apex
trigger AccountTrigger on Account (before insert) {
for (Account acc : Trigger.new) {
// ❌ BAD: SOQL inside loop
Contact c = [SELECT Id FROM Contact WHERE Email = :acc.Email__c LIMIT 1];
acc.Contact__c = c.Id;
}
}
This code hits SOQL limit if more than 100 records are inserted.
Better Approach (Bulkified):
apex
trigger AccountTrigger on Account (before insert) {
Set<String> emails = new Set<String>();
for (Account acc : Trigger.new) {
emails.add(acc.Email__c);
}
Map<String, Contact> contactMap = new Map<String, Contact>();
for (Contact c : [SELECT Id, Email FROM Contact WHERE Email IN :emails]) {
contactMap.put(c.Email, c);
}
for (Account acc : Trigger.new) {
if (contactMap.containsKey(acc.Email__c)) {
acc.Contact__c = contactMap.get(acc.Email__c).Id;
}
}
}
This uses 1 SOQL query instead of n queries.
How to Handle and Avoid Governor Limits
- Bulkify Your Code
- Never write SOQL or DML inside a loop.
- Always work with collections (List, Set, Map).
- Use Collections & Maps
- Combine queries using IN and process results via Map<Id, SObject> for fast lookups.
- Limit Record Scope in Batches
- Use Database.executeBatch() to process large data sets efficiently.
- Use @future, Queueable, or Batch Apex
- Offload long-running or external operations to asynchronous methods.
- Use Limits Methods
Salesforce provides methods to check remaining limits:
apex
System.debug(‘Remaining SOQL Queries: ‘ + Limits.getLimitQueries() + ‘ / ‘ + Limits.getQueries());
- Avoid Recursive Trigger Execution
Use static variables or Trigger Frameworks to prevent triggers from running multiple times unintentionally.
- Use Platform Tools Wisely
- Flows and Process Builder also consume limits!
- Use scheduled flows or subflows to break automation into chunks.
Monitoring Governor Limits
You can:
- View governor limits in Debug Logs
- Use Developer Console > Logs to spot LimitException
- Use Apex Exception Email (Setup > Apex Exception Email) to get alerts
Pro Tips for Developers
- Think in bulk — Always design as if you’re processing 200 records.
- Test at scale — Write test classes with 200 records to simulate worst-case scenarios.
- Log critical limits in production using custom logging utilities.
Conclusion
Governor Limits are Salesforce’s way of protecting shared resources—but they’re not roadblocks. When you understand and code around them properly, they help you write better, more scalable applications.
By following best practices like bulkification, asynchronous processing, and limit monitoring, you can make sure your code runs smoothly—even at scale.