Although the possibilities of technology today are seemingly endless, everything has its limits. In particular, Salesforce runs on a multitenant system – in other words, multiple Salesforce client applications use the same server for its resources. In order to maintain this architectural model, it’s crucial to ensure that one client application is not taking up too much bandwidth. To combat this issue, Salesforce incorporates governor limits to its application.

What are governor limits?

Governor limits are Salesforce’s way to ensure one client application isn’t monopolizing resources. They’re set limits that each client application has, regardless of which Salesforce edition is running. This can be anything from a number of SOQL queries per day to time spent per Apex transaction. If a limit is reached in a Salesforce org, an unhandled exception is issued by that limit’s governor, which tracks the limits in your org.

In addition to not allowing orgs to unnecessarily clog resources, governor limits also encourage developers to write clean code. Bad coding practices can lead to an unnecessary amount of DML or SOQL statements run, or even statements timing out. When working with these types of statements in Apex, we’re likely working with large batches of data. Therefore, it’s crucial to optimize our code to make sure we don’t hit these limits and risk exceptions being thrown. Best practices towards handling Apex code is known as bulkifying code – we’ll get to this in a bit.

What are governor limits in Salesforce?

Salesforce conveniently lists all of its governor limits in detail in the Salesforce documentation. Today, we’ll be going through a selection of these governor limits and how you can avoid hitting these limits. Limits are tracked by governors, and there are six of them to know of:

As an overview, here are some limits that you should be aware of:

Total number of SOQL queries issued 100
Total number of records retrieved by SOQL queries 50,000
Total number of SOSL queries issued 20
Total number of records retrieved by a single SOSL query 2,000
Total number of DML statements issued 150
Total heap size 6 MB (Synchronous), 12 MB (Asynchronous)
Maximum execution time for each Apex transaction 10 minutes

How to Find Limit Information in Your Org

For developers, the Limits class can be used to retrieve information about current usage statistics. This class includes a variety of methods to determine both how much has been used towards the limit, and how much is left. For example, the getDMLStatements() method returns the number of DML statements that have been executed, and the getLimitDMLStatements() method returns the number of remaining statements that can be executed. You can find all of the methods from the Limits class in the Salesforce developer documentation.

You can also configure Salesforce to send email alerts when Apex code is invoked that surpasses 50% of governor limits. Note that this is for per-request limits only, not per-org limits. To do this as an administrator, follow these steps:

  1. Navigate to Setup > Users.
  2. Select the user that you’d like to receive emails.
  3. Check the box for Send Apex Warning Emails.
  4. Select Save.

Best Practices for Clean Apex Code

As mentioned earlier, the best way to avoid hitting governor limits in Salesforce is to write clean, consolidated code – otherwise known as bulkifying code. When we bulkify code, we reduce the number of statements that need to be run. For example, if we run a SOQL statement before a for loop as opposed to during the for loop, we only have to run that statement once, as opposed to an indefinite number of times.

Here are some practices you can implement to ensure that you avoid exceeding governor limits:

Bulkify Your Code

Bulkifying Your Code is a way to make sure that your code is able to handle multiple records at a time. This can be accomplished by practices such as iterating through a list inside of a for loop, as well as several of the strategies used below.

Don’t Run DML Statements or SOQL Statements Inside FOR Loops.

If you’re processing a series of statements, you may be tempted to run these inside of a FOR Loop. But these statements, especially when dealing with an unknown number of values, will fail to scale properly and often lead to exceeding governor limits.

Let’s take a look at this example that inserts accounts:
trigger insertAccts on Account(before insert){
List<Account> myAccts [select id, name (select firstname, lastname, email, phone from Contacts)
from Account where Id IN:Trigger.newMap.keySet()];
List<Contact> updatedContacts = new List<Contact>{};
for (Account a: myAccts){
for (Contact c: a.Contacts){
update updatedContacts;

Here, you’ll notice that the DML statement, update updatedContacts, lives outside of the for loop. If this DML statement existed inside the for loop, it could execute any number of times, including above the DML execution limit. But if we place this statement outside of the for loop, the statement will run once no matter what.

Don’t Use Multiple For Loops, or Double For Loops, If It’s Not Necessary

To describe the importance of creating efficient code, let’s look at Big O notation. Big O is a term used often in computer science to describe the complexity of an algorithm. In Big O notation, we use n to describe the input.

So if we use a loop like this:
for (Account a: myAccts){
//do something

This would be O(n), as it would run n amount of times based on how many items are in the list myAccts.

But if we included a second for loop, it would become O(n^2), which is incredibly complex in comparison. Of course, like with our insert method above, sometimes we do need to use for loops. But whenever you’re writing Apex code that’s growing in complexity, ask yourself: is there a more efficient way to do this, especially if our input values could become very large?

Take Care When Querying Large Sets Of Data

Limits exist in Salesforce for both the number of results returned in a query and its heap size. You can avoid this by using a for loop:
for (List<Account> myAccts: [SELECT id, name, email from Account where ShippingState LIKE '%Texas%']) {
//do something

Additionally, when writing your queries, be sure to only query for the data that you need. In this example, we only selected id, name, and email. Querying more than what you need is inefficient and can contribute to your governor limits. Especially if you’re working with large data sets, refining your query however you can will help prevent returning so many unwanted results.

Consider Using One Trigger Per Object

One Trigger Per Object is a design pattern commonly used to keep all of your triggers for an object inside of one class. This design pattern not only consolidates your code but also gives you more control over order of operations when your triggers execute.

Consider Use of the Future Method

You can also use asynchronous methods when working with long-term data operations, which will run when space is available. Methods that need to be run asynchronously should be annotated with @future. Future methods must be static and can only return void types. Of course, with asynchronous methods, it is important to write clean and efficient code to ensure that performance is not heavily impacted. Slow execution can delay other methods that are waiting to be executed in the queue.

Write Thorough Test Classes

Salesforce has requirements for creating test classes, and for good reason. There’s a multitude of scenarios that can be covered with test classes, and ensuring your code is efficient and doesn’t hit governor limits is one of them. The Limits class we discussed earlier can be used as debug statements to see how much data is being processed in examples, what the limits for your org are, and overall determining how close you are to hitting those limits.

When you’re writing test classes, it’s important to note that any code between Test.startTest and Test.stopTest has its own set of governor limits. You can use this to your advantage to ensure that any other data operations in your test classes don’t impact what you’re testing.

I hope this introduction to Salesforce Governor limits was useful. And if you have any questions, feel free to reach out! 

Julie Anna Contino

Julie Anna Contino

Jr. Developer

Julie Anna is a junior developer with a passion for learning and problem-solving. She graduated with a Bachelor's degree in Computer Science and has four years of development experience. She's excited to be a part of the Salesforce ecosystem and combine her previous experience with her passion for helping clients thrive.

About Roycon
We’re an Austin-based Salesforce Consulting Partner, with a passion and belief that the Salesforce platform’s capabilities can help businesses run more efficiently and effectively. Whether you are just getting started with Salesforce or looking to realize its full potential, Roycon specializes in Salesforce Implementations, Salesforce Ongoing Support, and Salesforce Integrations, and Development. We’re the certified partner to guide the way to increase Salesforce Adoption, make strategic decisions, and build your Salesforce Roadmap for success.