Before knowing what governor limits in salesforce is, let us understand what Multitenancy is?
‘Multitenancy’ is a fundamental technology that cloud uses to share IT resources cost-effectively and in securely.
Salesforce has many servers across globe and the org or salesforce instance that you work in will be in one of those servers. There servers will have huge database and machines and are so powerful that each server can host multiple instances of salesforce from different companies. So obviously every application will share resources that are available in the server like processor, database, network etc. Everything works smoothly without any deadlock situation. Such sharing of resources among different applications is called multitenancy.
If you speak in general, in a single building there will be many houses and different owners will own individual houses and resources such has, common space, water, garden area electricity will be shared among those people. Here building is like a server and you house is like your own application. There can be multiple applications in a server just like multiple houses in a building.
In this blog we will discuss 2 topics
As salesforce works in multitenancy, there can be a situation where we may end up in infinite loop like situation or infinite recursion or an apex code which is taking too much time to execute etc. If such situation arises then it will affect performance of other applications that are in the server. To make sure that no one monopolizes the resources, salesforce has imposed governor limits.
Governor limits are restrictions imposed on different processes that are executed in salesforce. Processes can be SOQL query or Apex code or number of lines that can be executed.
There are different sections in which governor limits are set.
- Per-Transaction Apex Limits
- Per-Transaction Certified Managed Package Limits
- Lightning Platform Apex Limits
- Static Apex Limits
- Size-Specific Apex Limits
Per-Transaction Apex Limits
These limits count for each Apex transaction.
|Description||Synchronous Limit||Asynchronous Limit.|
|Total number of SOQL queries issued1||100||200|
|Total number of records retrieved by SOQL queries||50,000|
|Total number of records retrieved by Database.getQueryLocator||10,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 issued2||150|
|Total number of records processed as a result of DML statements, Approval.process, or database.emptyRecycleBin||10,000|
|Total stack depth for any Apex invocation that recursively fires triggers due to insert, update, or delete statements3||16|
|Total number of callouts (HTTP requests or web services calls) in a transaction||100|
|Maximum cumulative timeout for all callouts (HTTP requests or Web services calls) in a transaction||120 seconds|
|Maximum number of methods with the future annotation allowed per Apex invocation||50||0 in batch and future contexts; 1 in queueable context|
|Maximum number of Apex jobs added to the queue with System.enqueueJob||50||1|
|Total number of sendEmail methods allowed||10|
|Total heap size4||6 MB||12 MB|
|Maximum CPU time on the Salesforce servers5||10,000 milliseconds||60,000 milliseconds|
|Maximum execution time for each Apex transaction||10 minutes|
|Maximum number of push notification method calls allowed per Apex transaction||10|
|Maximum number of push notifications that can be sent in each push notification method call||2,000|
- Batch Apex, these limits are reset for each execution of a batch of records in the execute method.
- Although scheduled Apex is an asynchronous feature, synchronous limits apply to scheduled Apex jobs.
- With respect to SOQL limits (1)
- In a SOQL query with parent-child relationship subqueries, each parent-child relationship counts as an extra query
- The row counts from these relationship queries contribute to the row counts of the overall code execution.
- This limit doesn’t apply to custom metadata types. Custom metadata records can have unlimited SOQL queries.
- With respect to DML limitation (2), call to following methods count against DML statement.
- delete and Database.delete
- insert and Database.insert
- merge and Database.merge
- undelete and Database.undelete
- update and Database.update
- upsert and Database.upsert
- With respect to Trigger (3).
- Recursive Apex that does not fire any triggers with insert, update, or delete statements, exists in a single invocation, with a single stack.
- Recursive Apex that fires a trigger spawns the trigger in a new Apex invocation.
- The new invocation is separate from the invocation of the code that caused it to fire.
- Spawning a new invocation of Apex is a more expensive operation than a recursive call in a single invocation.
- There are tighter restrictions on the stack depth of these types of recursive calls.
- With respect to heap size (4).
- Email services heap size is 36 MB.
- With respect to CPU time (5).
- CPU time is calculated for the executing Apex code, and for any processes that are called from this code, such as package code and workflows.
- CPU time is private for a transaction and is isolated from other transactions.
- The portion of execution time spent in the database for DML, SOQL, SOSL, waiting time for Apex callouts are not counted against CPU time
- Limits apply individually to each testMethod.
- To determine the code execution limits for your code while it is running, use the Limits methods.
Per-Transaction Certified Managed Package Limits
Certified managed package: managed packages that have passed the security review for AppExchang get their own set of limits for most per-transaction limits. There’s no limit on the number of certified namespaces that can be invoked in a single transaction.
There’s also a limit on the cumulative number of operations that can be made across namespaces in a transaction. This cumulative limit is 11 times the per-namespace limit. For example, if the per-namespace limit for SOQL queries is 100, a single transaction can perform up to 1,100 SOQL queries.
This table lists the cumulative cross-namespace limits.
|Description||Cumulative Cross-Namespace Limit|
|Total number of SOQL queries issued||1,100|
|Total number of records retrieved by Database.getQueryLocator||110,000|
|Total number of SOSL queries issued||220|
|Total number of DML statements issued||1,650|
|Total number of callouts (HTTP requests or web services calls) in a transaction||1,100|
|Total number of sendEmail methods allowed||110|
All per-transaction limits count separately for certified managed packages except for:
- The total heap size.
- The maximum CPU time.
- The maximum transaction execution time
- The maximum number of unique namespaces
- These limits count for the entire transaction, regardless of how many certified managed packages are running in the same transaction.
- The code from a package from AppExchange, not created by a Salesforce ISV Partner and not certified, doesn’t have its own separate governor limits.
- Any resources used by the package count against the total org governor limits.
Lightning Platform Apex Limits
There are certain limitations that are enforced in lightning platform. These are not apex transaction limits.
|The maximum number of asynchronous Apex method executions (batch Apex, future methods, Queueable Apex, and scheduled Apex) per a 24-hour period1||250,000 or the number of user licenses in your org multiplied by 200, whichever is greater|
|Number of synchronous concurrent transactions for long-running transactions that last longer than 5 seconds for each org.2||10|
|Maximum number of Apex classes scheduled concurrently||100. In Developer Edition orgs, the limit is 5.|
|Maximum number of batch Apex jobs in the Apex flex queue that are in Holding status||100|
|Maximum number of batch Apex jobs queued or active concurrently3||5|
|Maximum number of batch Apex job start method concurrent executions4||1|
|Maximum number of batch jobs that can be submitted in a running test||5|
|Maximum number of test classes that can be queued per 24-hour period (production orgs other than Developer Edition)5||The greater of 500 or 10 multiplied by the number of test classes in the org|
|Maximum number of test classes that can be queued per 24-hour period (sandbox and Developer Edition orgs)5||The greater of 500 or 20 multiplied by the number of test classes in the org|
|Maximum number of query cursors open concurrently per user6||50|
|Maximum number of query cursors open concurrently per user for the Batch Apex start method||15|
|Maximum number of query cursors open concurrently per user for the Batch Apex execute and finish methods||5|
Static Apex Limits
Static apex is when you make a call to 3rd part application or when a batch apex is executed etc. It also includes limitations in deployment of apex. Below is the list of static apex limitations.
|Default timeout of callouts (HTTP requests or Web services calls) in a transaction||10 seconds|
|Maximum size of callout request or response (HTTP request or Web services call)1||6 MB for synchronous Apex or 12 MB for asynchronous Apex|
|Maximum SOQL query run time before Salesforce cancels the transaction||120 seconds|
|Maximum number of class and trigger code units in a deployment of Apex||5,000|
|Apex trigger batch size2||200|
|For loop list batch size||200|
|Maximum number of records returned for a Batch Apex query in Database.QueryLocator||50 million|
Size-Specific Apex Limits
There is certain limitation when writing an apex class or trigger. These limitations make sure that your apex clases, triggers and their methods are not overloaded.
|Maximum number of characters for a class||1 million|
|Maximum number of characters for a trigger||1 million|
|Maximum amount of code used by all Apex code in an org1||6 MB|
|Method size limit 2||65,535 bytecode instructions in compiled form|
There are many more limitations that are listed by salesforce.
How to Avoid Governor Limits.?
- One Trigger per Object
- Always write ONLY one trigger per object. You can handle the order of execution by context variables.
- Logic less Trigger
- Write a helper class for each trigger. Write different methods as per business logic. Call those helper methods as per context of trigger.
- Bulkify the code.
- Always write method so that it can handle multiple records at a time.
- Bulkify the trigger helper methods.
- Avoid SOQL queries OR DML operations in loop.
- Writing queries or DML statements in loop will count against governor limits NEVER write those in loop.
- Make use of List or Map if at all you need to process data.
- Use streamlining SOQL queries can substantially help writing efficient Apex code and avoid governor limits
- Use proper methods to handle bulk data
- If you are processing records more than 50,000 records, then wither use Batch apex
- You can also use future methods.
- Avoid Hardcoding IDs
- When deploying code from one environment to another ID will throw error.
- Try to get ID’s dynamically. Write methods to query and get the ID’s wherever possible. By doing so the logic will work even if environment changes because of deployment.