Apex Code is the Force.com programming language used to write custom, robust business logic. Apex is compiled and executed on the Force.com multitenant infrastructure, which is a shared resource across all customers, partners, and developers. Consequently, it is important that Apex code uses infrastructure resources efficiently.
This is where Apex governor limits come in. Governor limits are runtime limits enforced by the Apex runtime engine to ensure that code does not misbehave. This article presents an overview of Apex Code governor limits, why they are important, and how to design scalable, efficient Apex code.
Governor limits are runtime limits enforced by the Apex runtime engine. Because Apex runs in a shared, multitenant environment, the Apex runtime engine strictly enforces a number of limits to ensure that code does not monopolize shared resources. Types of limits that Apex enforces are resources like memory, database resources, number of script statements to avoid infinite loops, and number of records being processed. If code exceeds a limit, the associated governor issues a runtime exception that cannot be handled thereby terminating the request.
The term governor limits is specific to Apex and the Force.com platform, but the concept is not new. Traditional programming languages such as Java and .NET have similar limits for their associated Virtual Machines. For example, when a Java Virtual Machine is initiated, the heap size is specified and a runtime exception is thrown if that heapsize is exceeded. Similarly, if a .NET ADO or JDBC application doesn’t properly manage the open connections, for example, exceptions are thrown. Ultimately, governor limits provides Force.com with a deterministic way to ensure that code will always work and execute properly on the platform.
So why have governor limits? Multitenancy is one of the cornerstones of the Force.com platform that allows salesforce.com to ensure all customers are on the same version of the platform codebase, while providing the ability to customize their own environment. This allows customers, partners, and developers to share our infrastructure resources in a manner similar to how an apartment building shares it common area and facilities with all tenants. The benefit is a highly scalable infrastructure and platform that is equally shared across the entire user base. But to ensure that the server resources are not disproportionately used in an inefficient manner, Apex code has governor limits in place. Governor limits guarantee that no implementation of Apex will negatively impact other salesforce.com instances.
What is the scope of the governor limits? The limits will be applied to the code that executes beginning at that entry point, running through all subsequent code that is called until the code terminates.
Take for example an external client that invokes an Apex web services. All code that the Apex web service method executes, or causes to execute, is included in the limit calculations. The "causes to execute" is quite important here. If the web service method invokes a helper method in a different class, or adds a record to an object that has an associated trigger, then both the helper method and the trigger code contribute towards the governor limit.
Let's take another example: say an Account record is created and that causes an Account Apex trigger to initiate. That trigger performs a few queries, and then inserts some related Contact and Task records. And say the Contact and Task objects also have triggers enabled, which are subsequently invoked. All of the triggers and related code that is executed are considered as part of the same Apex request and therefore share the governor limits began counting when that initial Account trigger was invoked.
Governor limits are not specified for each separate trigger. The governor limits were calculated when the first Account trigger was initiated and the scope of those limits covered all corresponding code until the last trigger execution was completed.
To summarize, any Apex class, method, or trigger invoked by code executed within the entry point will count towards the same governor limits as it's a synchronous request.
You can find the definitive list of governor limits in the Apex Developer's Guide. This list of governor limits does change from release to release - in particular many governor limits are simplified and the limits are sometimes raised.
So far, we've covered how to invoke Apex synchronously and how governor limits are calculated on those synchronous transactions. There is also an option to execute Apex in an asynchronous mode. This approach can offload some of the processing by creating a separate, independent Apex request that runs asynchronously, and which can keep your code well within the governor limits.
To run Apex asynchronously, use the @future annotation when defining the Apex method. By default, Apex runs synchronously in a single transaction. The key benefit of running the Apex asynchronously is to remove the business logic from the synchronous transaction and therefore the user won't have to wait for the processing. In other words, offloading the business logic processing to the async Apex, there is less logic to process synchronously and the user experience is more efficient.
An additional benefit of running the Apex asynchronously is to get higher governor limits to complete your processing. Governor limits do still get enforced with asynchronous Apex, but the limits are slightly higher than normal Apex transactions. Not only do you get higher limits, those governor limits are independent of the limits in the synchronous request that queued the async request initially. Remember, the Apex code that runs asynchronously is a separate Apex request than the synchronous request. Therefore, you have two separate "entry points" - or two Apex invocations.
Let's use an example to better articulate the value and benefit of using @future to get higher governor limits. Let's say we have a trigger on the Account object and the Apex logic wants to update all related Contacts whenever the Account is updated. Since the Account has a 1-to-many relationship with Contacts, it's possible to have many thousand of Contacts records related to a specific Account. In this scenario, an Apex trigger invoked by a single Account update operation would not be able to update several thousand Contacts synchronously. But if the Apex is re-factored to implement asynchronous Apex and perform the query and update of those related contacts within a @future Apex method, that asynchronous Apex governor limits will allow up to 50,000 records to be retrieved in SOQL queries and up to 10,000 records can be updated through DML operations.
A final benefit of using asynchronous Apex and the @future annotation is to invoke an Apex callout from within an Apex Trigger. If there is a requirement to invoke a third party web service from within an Apex trigger, you will need to execute that callout asynchronously by defining the web service request and response handling in a @future method.
As I like to say, don't forget your test methods! Please review the related article, An Introduction to Apex Code Test Methods if you are unfamiliar with Apex test methods.
When it comes to governor limits and test methods, the key is to create a large enough dataset in the test method to ensure your Apex solution scales efficiently and doesn't throw any runtime exceptions.
So for example, if you have a trigger on the Account object, make sure to create upwards of 200 Account records in the test method itself, then insert or update those records to cause the Apex trigger to be invoked by all 200 records in a single transaction. The point is to make sure that the trigger code can scale within the governor limits. There a sample available in the article.
Writing efficient and scalable Apex code is critical to the overall success of your Apex solution. Understanding the reasons why governor limits exist and how they are calculated is important in achieving this. Governor limits are not intended to limit your Apex solutions or prevent you from writing rich, complete solutions. Instead, they are enforced to ensure efficient and scalable code is executing on the Force.com platform in a shared, multitenant environment.
Andrew Albert is a Technical Evangelist at salesforce.com, focusing on the Force.com platform. He works with ISVs and developers that are looking to build applications on the Force.com platform.