Salesforce Governor Limits: The Guide I Wish I Had on Day One
Understand SOQL, DML, CPU Time, and Heap Size through simple analogies, Apex examples, and practices that prevent the most common limit exceptions.
If you are new to Salesforce, sooner or later you will hear someone say, "we hit a limit," and wonder what that means. Let us understand the idea before it surprises you in a deployment or a production transaction.
First: why do the limits exist?
Salesforce is a multi-tenant platform. Your organization and thousands of other organizations run workloads on shared platform infrastructure.
Imagine an office building where every company shares the elevators, electricity, and internet connection. If one tenant attempts to consume an unreasonable amount of a shared resource, everyone else can be affected.
Governor Limits are execution boundaries that control how many resources a single transaction can consume. They protect the platform and require solutions to work efficiently at scale.
1. SOQL limit: how many questions you can ask the database
Common synchronous limit: 100 SOQL queries per Apex transaction.
Every time your code sends a SELECT query to the database, it consumes part of that budget. If the transaction exceeds the limit, Salesforce stops the execution with a limit exception.
The analogy
Imagine a library where the librarian allows at most 100 requests per visit. Instead of returning to the desk 50 times for one book, you provide one list and ask for all relevant books together. One request, many results.
// AVOID: one query for every Account.
for (Account acc : accounts) {
List<Contact> contacts = [
SELECT Id, Name
FROM Contact
WHERE AccountId = :acc.Id
];
}
// BETTER: collect the IDs and query once.
List<Contact> contacts = [
SELECT Id, Name, AccountId
FROM Contact
WHERE AccountId IN :accountIds
];
2. DML limit: how many times you can write to the database
Common synchronous limit: 150 DML statements per Apex transaction.
DML includes operations such as insert, update, delete, and upsert. A statement counts whether it receives one record or a collection.
The analogy
Return to the library. If you return each of 200 books one at a time, you make 200 desk visits. If you place them on a cart and return the collection together, this analogy treats it as one operation.
// AVOID: one insert per record.
for (Contact con : newContacts) {
insert con;
}
// BETTER: one insert for the collection.
insert newContacts;
The pattern is the same: loops combined with database access require careful design.
3. CPU Time limit: how long your code can think
Common synchronous limit: 10,000 milliseconds, or 10 seconds, per Apex transaction.
This budget measures CPU time used by Apex and relevant automation invoked in the same transaction. Expensive loops, repeated transformations, and inefficient comparisons can consume it quickly.
The analogy
Imagine an exam with a strict ten-second timer. If the timer ends, the execution stops even if you were close to the answer.
// EXPENSIVE: every Account scans every Contact.
for (Account acc : accounts) {
for (Contact con : allContacts) {
if (con.AccountId == acc.Id) {
// Do something
}
}
}
// BETTER: index Contacts by AccountId.
Map<Id, List<Contact>> contactsByAccount =
new Map<Id, List<Contact>>();
for (Contact con : allContacts) {
if (!contactsByAccount.containsKey(con.AccountId)) {
contactsByAccount.put(con.AccountId, new List<Contact>());
}
contactsByAccount.get(con.AccountId).add(con);
}
for (Account acc : accounts) {
List<Contact> relatedContacts = contactsByAccount.get(acc.Id);
// Direct Map lookup instead of scanning the entire list again.
}
With 1,000 Accounts and 5,000 Contacts, the nested-loop approach can perform up to five million comparisons. The second approach scans the collections once and uses a Map for direct lookup.
4. Heap Size limit: how much memory your code can occupy
Common synchronous limit: 6 MB per Apex transaction.
Heap is the memory used by variables, collections, objects, strings, and other data that remain alive during execution.
The analogy
Imagine a fixed-size desk. Every document and tool you need must fit on it. If you keep too much in memory at the same time, you run out of space.
// RISKY: broad query with no filter and an unnecessary large field.
List<Contact> allContacts = [
SELECT Id, Name, Description
FROM Contact
];
// BETTER: filter and select only what the use case needs.
List<Contact> contacts = [
SELECT Id, Name
FROM Contact
WHERE CreatedDate = THIS_MONTH
LIMIT 500
];
A broad query may hit other limits before heap, such as the total number of SOQL rows. The answer is not to add an arbitrary LIMIT; filters and processing strategy must still satisfy the business requirement.
When a large data volume is genuinely required, Batch Apex can split the work into smaller transactions. Each execute invocation receives a fresh set of limits. The scope can be configured, and 200 records is the default batch size when none is specified.
Visual summary
| Limit | What it controls | Common synchronous value | Analogy |
|---|---|---|---|
| SOQL | Database queries | 100 | Requests to the librarian |
| DML | Write statements | 150 | Visits to the returns desk |
| CPU Time | Processing time | 10 seconds | Exam timer |
| Heap Size | Memory in use | 6 MB | Desk size |
The pattern that keeps you safe
The four limits point to one principle:
- Do not query one record at a time. Query sets of records.
- Do not write one record at a time. Group DML operations.
- Do not compare everything with everything. Index data with Sets and Maps.
- Do not load unnecessary data. Select only the required fields and rows.
Salesforce did not create Governor Limits to frustrate developers. They are part of how the platform protects a shared environment and encourages solutions that handle volume safely.
Once you learn to design for these boundaries, your code usually becomes clearer and more scalable on any platform.
Official sources for further study
Want to keep learning Salesforce and OmniStudio through hands-on content?
Explore my articles, OmniStudio 365, and the OmniStudio in Practice course.
Explore OmniStudio 365