DEV Community

Renuka Singh
Renuka Singh

Posted on

Salesforce Governor Limits: 7 Apex Best Practices Every Developer Should Know

Salesforce runs on a multitenant architecture, where multiple organisations share platform resources. To maintain stability and performance, Salesforce applies governor limits to operations such as database queries, data manipulation, and CPU usage.

For Apex developers, understanding these limits is essential when building triggers, integrations, and custom business logic. Code that works with one record may fail when processing hundreds of records in a single transaction.

The solution is to design Apex with bulk processing, efficient database operations, and realistic testing in mind.

  1. Understand How Governor Limits Affect Apex

Governor limits restrict resource consumption within a transaction. Depending on the execution context, limits may apply to SOQL queries, DML statements, CPU time, heap size, and other operations.

For example, repeatedly querying records inside a loop can exhaust the transaction's SOQL query allowance.

Rather than treating limits as obstacles to work around, developers should use them as design constraints from the beginning.

Always consult the current Salesforce governor limits documentation because specific limits and behaviours depend on the execution context.

  1. Avoid SOQL Queries Inside Loops

One of the most common Apex performance problems is placing database queries inside loops.

Avoid this pattern:

for (Contact contactRecord : contacts) {
Account accountRecord = [
SELECT Id, Name
FROM Account
WHERE Id = :contactRecord.AccountId
LIMIT 1
];
}

If many contacts are processed, the code can execute too many queries.

Instead, collect the required IDs and query the records in a single operation.

Set accountIds = new Set();

for (Contact contactRecord : contacts) {
if (contactRecord.AccountId != null) {
accountIds.add(contactRecord.AccountId);
}
}

Map accountsById = new Map(
[
SELECT Id, Name
FROM Account
WHERE Id IN :accountIds
]
);

The map makes it easy to retrieve account information by ID without repeating database queries.

  1. Bulkify Triggers and Service Methods

Bulkification means designing code to process collections of records instead of assuming that only one record will be handled at a time.

Salesforce triggers can receive multiple records during imports, integrations, or bulk updates. Your logic should therefore iterate over the trigger collection and prepare data operations for the entire batch.

For example, rather than inserting one related task for every record inside a loop, build a list of tasks and insert them together.

List tasksToInsert = new List();

for (Contact contactRecord : contacts) {
tasksToInsert.add(
new Task(
Subject = 'Follow up',
WhoId = contactRecord.Id
)
);
}

if (!tasksToInsert.isEmpty()) {
insert tasksToInsert;
}

This reduces the number of DML statements and makes the logic more suitable for bulk processing.

  1. Use Collections Efficiently

Apex collections such as List, Set, and Map help organise data and reduce repeated operations.

Use a Set when you need unique IDs, a List when you need an ordered collection of records, and a Map when records must be accessed efficiently by key.

Choose the collection based on the task rather than creating unnecessary structures.

Also avoid repeatedly searching large lists when a map or set can provide a simpler lookup. Efficient collection usage can improve readability and reduce unnecessary processing.

  1. Keep DML Operations Outside Loops

Database operations such as insert, update, delete, and upsert should generally be performed on collections rather than one record at a time.

A bulk DML operation helps reduce statement consumption and makes transaction behaviour easier to manage.

However, bulkification does not remove every limit. The number of records processed, validation rules, automation triggered by DML, and other operations can still affect performance.

Check for empty collections before executing DML, and ensure your code handles partial or complete failures according to the business requirements.

  1. Test With Realistic Record Volumes

Apex code should be tested with more than a single example record.

Include test cases with multiple records, missing optional values, different relationships, and conditions that trigger different business rules.

Verify that the code produces the expected results and does not rely on the order in which records happen to be processed.

Pay attention to other automation that runs during database operations, including flows and triggers on related objects. These processes can contribute to transaction resource consumption.

A realistic test strategy helps uncover issues before the code reaches production.

  1. Monitor, Review, and Refactor

Governor-limit problems are not always obvious during initial development. As data volumes and business requirements change, previously acceptable code may become inefficient.

Review debug logs, exception details, and relevant performance information when investigating failures. Look for repeated queries, unnecessary calculations, excessive database operations, and recursive automation.

Refactor the code when a clearer or more efficient design is available. For complex Salesforce environments, reviewing the wider automation and integration architecture can also help identify the underlying cause of repeated failures.

How Professional Salesforce Support Can Help

Governor-limit issues may involve more than one Apex class. Triggers, flows, integrations, and existing customisations can all contribute to the behaviour of a transaction.

Businesses that need help improving their Salesforce architecture can explore Salesforce consulting services from iBirds Software Services.

For ongoing troubleshooting, maintenance, and system improvements, Salesforce support services provide another relevant resource.

Conclusion

Governor limits are an important part of developing reliable Salesforce applications. By avoiding queries and DML operations inside loops, bulkifying code, using collections effectively, and testing realistic scenarios, developers can build Apex that handles larger workloads more safely.

The key is to consider resource usage from the start rather than waiting for a limit exception to appear in production.

Top comments (0)