What are Salesforce Governor Limits? Best Practices & Examples

Share this article...

Salesforce governor Limits are a concept that exists because Salesforce and Apex run in a multitenant environment. Multitenancy is a fundamental technology that sits alongside cloud computing.

Back when on-premise servers ruled the earth, you would purchase one or many servers to sit within your office or home. These servers would run your applications, and you would own the full processing power and storage capacity. You would also be responsible for the upkeep, maintenance, and upgrades. Fast forward to today, multitenancy allows us to share resources with other users of an application, in a cost-effective and secure manner.

Salesforce Multitenancy

Due to the nature of multitenancy and the fact we are sharing resources, governor limits are in place to ensure that any Apex we develop, does not monopolize the shared resources we are allocated.

Imagine this: there are 100 flats in a single apartment building. The 100 flats share resources: water, electricity, gas and wi-fi bandwidth. Imagine if several flats started some bitcoin mining which started to hog all of the electricity. Then imagine if some other flats started to download huge 4k video files from the interwebs. And then also imagine if some other flats were running baths all at the same time. If you lived in this apartment building, things would turn into a nightmare: you wouldn’t be able to stream any videos online in any reasonable time frame, your electricity bills would quadruple in a single month and the water pressure in your shower would decline to an embarrassing trickle.

The apartment building is a Salesforce instance (also known as a pod or server). The flats are the individual Salesforce orgs (there can be tens of thousands of orgs on a single sever). The distribution of shared resources is the multi-tenancy architecture.

This analogy helps to explain why governor limits are so helpful – they prevent inconsiderate actors from hogging database, memory, network or processor resources that you and other customers on the same server need to effectively run their business processes in the cloud. So, governor limits dictate what your code can and cannot do when it is executed on the Salesforce platform. And this contributes to the scalability of the platform since the resource allocation is defined.

Salesforce Governor Limits

There are many different types of governor limits, some of which are tied to your Salesforce edition. For example, Professional Edition enables one to have 50 custom objects but 2,000 for Unlimited and Performance.

Some other governor limits have ‘soft’ limits that can either be solved by Salesforce or by purchasing additional add-ons. For example, the current limit is 6MB of Apex code per org but this can be increased on a case by case basis by Salesforce Support. Other limits are based on a combination of both your Salesforce edition but also the number of user licenses on the org. For example, API and data storage limits.

Other governor limits are associated more with programming in Apex: for example, an Apex class / execute anon script can only have 100 SELECT statements per synchronous transaction. Some of these limits are ‘hard’, meaning that they cannot be increased and so a new approach by the developer would be needed to achieve the desired result.

This trailhead on multi-tenancy and this Salesforce Summary article go into more detail on this subject.

Types of Governor Limits

 Per-Transaction Apex Limits – These limits count for each Apex transaction. For Batch Apex, these limits are reset for each execution of a batch of records in the execute method.

 Per Transaction Certified Managed Package Limits – If a managed package developed by a Salesforce ISV has passed security review, they are provided with generally higher per-transaction limits.

Lightning Platform Apex Limits – These limits aren’t specific to an Apex Transaction and are enforced by the Lightning platform.

Static Apex Limits – Apex Limits that are applied across all transactions

Size-Specific Apex Limits – Apex Limits related to the size of code.

Miscellaneous Apex Limits – Other Limits

Why are Governor Limits Important?

Governor Limits are a concept that all Salesforce Developers (and Admins to a lesser extent), must grasp. They will fundamentally shape the way that you architect Salesforce solutions, as well as how the code is written.

If a Salesforce Governor Limit is hit, the associated governor issues a runtime exception that cannot be handled. Which translates to, your code breaks and won’t work.

Governor Limit Best Practices

As per the official docs, there are a huge number of different types of governor limits. This article will cover some of the more common ones associated with Apex programming and outline approaches that can be taken to resolve them.

SOQL 100 Limit

One of the most well known governor limits is that an apex class / execute anonymous script can ‘only’ have 100 SELECT statements per apex transaction.

By the way, an apex transaction is a set of operations that are executed in a single unit. For example, when a trigger runs on every Account that has its name updated, processing is done to update all references across tasks and events from the old Account name to the new Account name. The sum of operations and resources that are leveraged that take place to achieve this is the apex transaction.

To demo this particular governor limit, go to a sandbox and navigate to the Developer Console. Either input cmd + E or Debug | Open Execute Anonymous Window and input the following:

for (integer i = 0; i <= 100; i++)
{
    Integer countOfAccounts = [SELECT COUNT() FROM Account];
}

Upon highlighting and then selecting ‘Execute Highlighted’ in the Dev console, you’ll receive the following error:

This is happening as per the docs: you can only have 100 SELECT statements in a synchronous context.

Governor Limit Fix

Oftentimes, this governor limit will be hit because there is a SOQL statement in a for loop; which is considered on of the ‘cardinal sins’ of programming in Apex.

List<Account> accounts = [SELECT Id, Name FROM Account];
List<Integer> contactCount = new List<Integer>();
for (Integer i = 0; i <= accounts.size(); i++)
{
    Integer count = [SELECT COUNT() FROM Contact WHERE AccountId IN : accounts ];
    contactCount.add(count);
}

The moment that there are more than 99 accounts in the variable ‘accountList’, then the code will fail.

A simple solution is simply to move all SOQL statements outside of for loops, and especially if the for loop iterator is dynamic (the number of accounts in the list could change but if the iterator is a number, then that is fixed). To do that, you’ll likely be depending more on other collections and inventive SOQLs.

An approach can be like so:

Map<Id, Account> accountMap = new Map<Id, Account>([SELECT Id FROM Account]);
Map<String, Integer> accountNamesAndRespectiveContactCounts = new Map<String, Integer>();
for(Account accountObject : [SELECT Name, (SELECT Id FROM Contacts) FROM Account WHERE Id IN :accountMap.keySet()])
{    
    accountNamesAndRespectiveContactCounts.put(accountObject.Name, accountObject.Contacts.size());
}
system.debug('accountObject map is: ' + accountNamesAndRespectiveContactCounts);

DML 150 Limit

Probably the second most well known governor limit concerns the number of DML operations in a single transaction. As per the docs, the limit is 150:

To demonstrate this, in a developer sandbox, you can run the following execute anonymous code:

List<Account> accountList = new List<Account>();
Account accountObject;
for (Integer i = 0; i < 150; i++)
{
    accountObject = new Account();
    accountObject.Name = 'Test ' + i;
    accountList.add(accountObject);
}
insert accountList;

This will create 150 Accounts. 

Now, try to execute the following code:

Contact contactObject;
for (Account accountIterator : [SELECT Id, Name FROM Account])
{
    contactObject = new Contact();
    contactObject.AccountId = accountIterator.Id;
    contactObject.LastName = 'Surname ' + accountIterator.Name;
    insert contactObject;
}

Your execute anon should look like this:

You will hit the following error:

DML 150 Limit Fix

Again, it’s a fairly straight forward fix. You should not use DML statement inside for loops (btw this is something that good code scanning tools such as PMD will pick up on) and instead, you should leverage collections to store the data and then when you do a DML operation on a collection, it only counts as one DML!

To demonstrate that, let’s execute the following code and for good measure, let’s leverage some of the helpful methods from the Limits class.

List<Contact> contactList = new List<Contact>();
Contact contactObject;
for (Account accountIterator : [SELECT Id, Name FROM Account LIMIT 150])
{
contactObject = new Contact();
contactObject.AccountId = accountIterator.Id;
contactObject.LastName = 'Surname ' + accountIterator.Name;
contactList.add(contactObject);
}
if (contactList.size() > 0)
{
insert contactList;
}
system.debug('Size of contact list is: ' + contactList.size());

system.debug('Count of DML statements: ' + Integer.valueOf(Limits.getDmlStatements()));

Opening up the debug log will display the following:

That is very cool – you could have a collection with tens of thousands of records (or much more) and yet still only use 1 of your 150 available DML statements. Talk about efficient!

Exercises

Practice makes perfect, so let’s do some exercises together. Good luck!

Question 1

How would you refactor the below

Task taskObject;
for (Contact contactObject : [SELECT Id, AccountId, LastName FROM Contact])
{
    taskObject = new Task(WhoId = contactObject.Id);
    insert taskObject;
}

Answer 1

List<Task> tasks = new List<Task>();
Task taskObject;
for (Contact contactObject : [SELECT Id, AccountId, LastName FROM Contact])
{
    taskObject = new Task(WhoId = contactObject.Id);
    tasks.add(taskObject);
}
 
insert tasks;</pre>
<strong>Question 2</strong>

How would you refactor the below?
<pre>

for (Account accountObject : [SELECT Id, Description FROM Account])
{
    Integer countOfEvents = [SELECT COUNT() FROM EVENT WHERE WhatId =: accountObject.Id];
    if (countOfEvents &amp;amp;amp;gt; 0)
    {
        accountObject.Description = String.valueOf(countOfEvents);
    }
    update accountObject;
}

Answer 2

Map<Id, Account> accountsMap = new Map<Id, Account>([SELECT Id FROM Account]);
Set<Id> accountsWithEvents = new Set<Id>();
Map<String, String> eventsPerAccount = new Map<String, String>();
List<Account> accountList = new List<Account>();
 
for (Event eventObject : [SELECT Id, WhatId FROM Event WHERE WhatId IN : accountsMap.keySet()])
{
    accountsWithEvents.add(eventObject.WhatId);
}
for (AggregateResult aggregate : [SELECT COUNT(Id) theId, WhatId theWhatId FROM Event WHERE WhatId IN :accountsWithEvents GROUP BY WhatId])
{
    eventsPerAccount.put(String.valueOf(aggregate.get('theWhatId')), String.valueOf(aggregate.get('theId')));  
}
 
for (Account accountObject : [SELECT Id, Description FROM Account WHERE Id IN : eventsPerAccount.keySet()])
{
    if (accountObject.Description != eventsPerAccount.get(String.valueOf(accountObject.Id)))
      {
    accountObject.Description = eventsPerAccount.get(String.valueOf(accountObject.Id));
    accountList.add(accountObject);
      }
}
 
if (accountList.size() > 0)
{
    update accountList;
}

The above answer is a way to achieve the outcome. It leverages AggregateResult and different collections to update the Description field on the Account object with the value of the number of event records that the account has.

Conclusion

In conclusion, there are many different types of governor limits across Salesforce and for good reason - to help us become more efficient developers and admins. There are some general patterns that you can adopt to ensure that you stay below the limits. Generally speaking, the most well-known limits are those around SOQL and DML limits in a single transaction. You also learned that getting past governor limits can be challenging and fun at the same time 🙂

Thank you for reading.

2 thoughts on “What are Salesforce Governor Limits? Best Practices & Examples

  1. Avatar

    Raghavendra srinivas Philkana

    Reply

    Excellently written article .. great!
    Very important info put in simple amd easy to understand terms.

    Thank you so much 🙂

Leave a Reply