Governors in Apex Code

(Redirected from Governor Limits in Apex Code)

Abstract

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.

What are Apex Governor Limits and Why Have Them?

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.

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.

How are Governor Limits Calculated?

There are a number of factors that determine what governor limit is used, and when it is applied. This section looks at these factors. After covering the main factors, this section ends with a few concrete use cases illustrating how these governor limits are applied in various contexts.

Factors that determine governor limits

Governor limits are calculated at runtime based on how the Apex code is invoked and how many records caused the code to be invoked. It also depends on the specific governor limit.

So think of governor limits as calculated by 3 key factors:

  • how was the Apex invoked - the entry point
  • how many records initiated the Apex
  • what governor limit is in question

The documentation contains a full list of all governor limits and notes on how they are calculated.

Entry points

Governor limits are applied based on the entry point of your code. An entry point is defined as the first action that results in the code being executed. For example, if an external web service client invokes an Apex web service, the method which serves that web service is the entry point.

There are several ways to invoke Apex:

  • Apex Trigger – A trigger is Apex code that executes before or after the following types of operations on database objects: insert, update, delete, merge, upsert, and undelete. These are similar to database triggers written in Oracle’s PL/SQL or Microsoft’s tSQL. One important note is that all Apex triggers are bulk triggers. That means that a trigger can be invoked by a single record transaction or by a bulk operation such as an API call that has a batch of up to 200 records. For example, if I create an Account in the user interface, any triggers on the Account object will be invoked with a single record as the input. Conversely, if there is an integration sending a batch of 200 records to the API, that same Apex trigger on the Account object will be invoked only ONCE, but with 200 Account records as input.
  • Apex Web Service – Apex class methods can be exposed as custom Force.com Web Services API calls. By simply using the Apex keyword webService on a global class method, an Apex method can be exposed as a custom API and invoked by an external server.
  • Anonymous Block – An anonymous block is a piece of Apex code that does not get stored in the metadata, but that can be compiled and executed using one of the following:
    • System Log console
    • Force.com IDE
    • The executeAnonymous Force.com Web Services API call
You can use anonymous blocks to quickly evaluate Apex on the fly, such as in System Log console or the Force.com IDE, or to write code that change dynamically at runtime.
  • Visualforce Controller – An Apex class that implements the logic behind Visualforce page(s).
  • RunTests – This is a Force.com Web Services API call used to execute test methods. It can be invoked by running tests through the Force.com IDE or through the User interface under Setup->Develop->Apex Classes->Run All Tests. It also can be invoked in the Force.com Migration Tool.

Governor Limits Scope

We just talked about how Apex can be invoked and how that impacts the governor limits. But what is the scope of those 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 determined 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.

Examples

The best way to illustrate these 3 key factors is with examples.

Example 1: Apex Trigger invoked by the user interface

An Apex trigger has been deployed on the Account object and a user creates a new Account record through the user interface. When the user hits the "Save" button, that record is inserted into the Account table and the trigger is invoked. At this point, Apex calculates the governor limits to apply to the Apex code. All normal trigger limits are applied. Here is a sample (and not a comprehensive list) of those limits:

  • Maximum of 20 SOQL queries
  • Maximum of 1,000 records retrieved by SOQL queries
  • Maximum of 10,000 script statements can be executed.

Example 2: Apex Trigger invoked by a batch of records through the Force.com Web Services API

Let’s extend the previous example where we have an Apex Trigger on the Account object. But instead of a single record being created through the user interface, a batch of 200 records is inserted into the Account table through the Web Services API. That single API call invokes the Apex trigger, but now the trigger is invoked with 200 records. That is important since the 200 records will increase several of the governor limit calculations. For example:

  • Maximum of 20,000 records retrieved by SOQL queries.
  • Maximum of 50,000 script statements can be executed.

Notice how those two sample governor limits are substantially higher since the Apex trigger was invoked due to a batch of records instead of a single record. The number of records that can be retrieved in a SOQL query has scaled 20 times as compared to when the trigger was invoked by a single record through the user interface. This helps illustrate the point that the number of records invoking the Apex impacts the governor limit calculation.

Example 3: Apex class (controller) is invoked by a Visualforce page

If using a custom controller or controller extension, a Visualforce page implements its business logic in an Apex class. And when an Apex method is invoked by the Page in that Apex controller, the context of the governor limits are different than in our previous two examples that was trigger-based. So let's use a specific example. Let's say a Visualforce page has a button that when clicked, invokes some logic in the Apex controller to query and update some related records. A sample of the governor limits will be calculated as followed:

  • Maximum of 100 SOQL Queries
  • Maximum of 10,000 records retrieved by SOQL queries.
  • Maximum of 100 DML statements (insert, update, delete)

To elaborate on the Visualforce page interaction with the Apex controller; when that Apex method is completed and returns control to the Visualforce page, that specific Apex request is complete. Therefore, if a user clicks the button again or any other user interactions initiates an Apex method, that new action is a new Apex request and new governor limits are allocated.

Synchronous vs Asynchronous Apex

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 similar to when Apex is invoked through Execute Anonymous or a Visualforce Controller. And 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. The default trigger governor limit of 1000 records would be exceeded. 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 10,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.

Testing Governor Limits

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.

Summary

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.

References

About the Author

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.