Warning

Fraudulent domains such as innostaxtech.com or innostaxtechllc.com are NOT affiliated with Innostax. Official communication only comes from @innostax.com. We never request money, banking details, deposits, or equipment purchases during hiring.

Navigating the Salesforce Apex Governor Limits

Master Salesforce Apex Governor Limits with best practices for SOQL, DML, CPU time, heap size, callouts, and building scalable, high-performance applications.

salesforce-energy
Key takeaways
  • 1 Salesforce Programmatic Tools: Salesforce's programmatic tools, including Apex, Visualforce, and Lightning Web Components, empower developers to create highly customized solutions, automate complex processes, and seamlessly integrate with external systems for enhanced CRM functionality.
  • 2 APIs for Seamless Integration: Salesforce's REST and SOAP APIs facilitate robust and versatile integration with external applications, ensuring smooth data exchange and creating a unified ecosystem that enhances the overall efficiency and interoperability of enterprise systems.
  • 3 Customization and Scalability: Salesforce's programmatic tools provide unparalleled customization and scalability, allowing developers to implement advanced business logic, create dynamic user interfaces, and optimize performance for growing organizations with unique and complex requirements.

Introduction to Salesforce Apex

Salesforce Apex, the powerful programming language for the Salesforce platform, enables developers to build robust and scalable applications. Salesforce imposes specific limits on Apex code execution known as “governor limits” to maintain a stable and reliable environment. These limits prevent poorly written or resource-intensive code from negatively impacting the performance of the Salesforce platform. In this blog post, we’ll explore the Salesforce Apex governor limits, understand their significance, and discuss strategies for optimizing code to ensure a smooth and efficient application.

Understanding Governor Limits

Governor limits in Salesforce are essentially a set of runtime constraints that restrict the amount of resources and data that a piece of Apex code can consume during execution. These limits exist to prevent monopolization of resources and to ensure that all organizations sharing the Salesforce infrastructure have a fair and predictable experience. Common governor limits include:

Governor LimitDescription
CPU Time LimitEvery Apex transaction is allocated a certain amount of CPU time.
SOQL and SOSL Query LimitsControl the number of records that can be queried in a single transaction.
DML Statement LimitsRestrictions on the number of records that can be inserted, updated, deleted, or undeleted.
Heap Size LimitRestricts the amount of memory (heap) available for Apex code execution.
Governor Limits on CalloutsLimits the number of callouts that can be made in a transaction to external services.

Why Governor Limits Exist in the First Place

It’s easy to see governor limits as an obstacle, but they’re really a byproduct of how Salesforce is built. Unlike a traditional application where you control the server, Salesforce runs on a multi-tenant architecture — meaning your org shares the same physical infrastructure with thousands of other organizations at the same time.

Without hard limits, a single inefficient trigger or a runaway loop in one company’s org could soak up CPU and memory that other customers depend on. Governor limits act as a fairness mechanism, making sure no single transaction can degrade performance for anyone else sharing that infrastructure.

This is also why governor limits are enforced per-transaction rather than per-user or per-org in most cases. A transaction — whether it’s triggered by a button click, an API call, or a scheduled job — gets its own fresh allocation of resources, and once it crosses a threshold, Salesforce throws an uncatchable LimitException and rolls back everything in that transaction. There’s no partial credit; the whole operation fails as a unit, which is precisely why designing around these limits from the start matters more than trying to patch around them later.

Optimizing Code for Governor Limits

To build efficient and scalable applications on the Salesforce platform, developers need to be mindful of governor limits. Here are some best practices for optimizing code:

Best PracticeDescription
Bulkify Your CodeDesign your code to handle bulk data processing rather than focusing on individual records.
Limit the Use of SOQL Queries in LoopsMinimize the number of SOQL queries inside loops to avoid hitting the query limit.
Use Asynchronous ProcessingConsider using asynchronous processing with features like Batch Apex or Queueable Apex.
Avoid Recursive TriggersImplement trigger controls to prevent recursion and avoid hitting CPU time limits.
Monitor and Analyze PerformanceRegularly monitor your application’s performance using Salesforce’s built-in tools.

Bulkification: The Concept Behind Most Limit Issues

If there is one concept that fixes more governor limit issues than any other single practice, it is bulkification. The idea can’t be represented concisely in a best practices table, so we need to explain it in more detail.

The important detail here is that Salesforce triggers do not fire once per record. They fire once per transaction, where a transaction can include anywhere from 1 record to 200 (the default batch size). Triggers at this level often have a common logical error: developers who are used to working with single record operations in other languages such as Java or C# may write the Apex as if it is being executed for only one record, resulting in queries or DML operations inside loops over Trigger.new

The correct approach is to always write Apex triggers in such a way that a single record being processed is representative of all possible records being processed in a trigger. What this usually means is:

Querying related records once, outside of any loop, using a single SOQL query with an IN clause

Storing collections of records that need to be inserted, updated, or deleted in lists, and performing single DML operations on these lists

Using maps to associate related records (often using the record ID as a key) rather than querying or looping

Once you develop this muscle memory, most of these issues will appear less frequently, regardless of how much data is flowing through your application.

Tools for Monitoring and Debugging Governor Limits

Being aware of the limits is one thing, but being able to identify when a certain process is going to exceed the limits is another. Some tools that I find helpful to ensure that I’m not reaching the limits are:

Debug Logs: Salesforce’s debug logs tell you how many SOQL queries, DML statements, and CPU time in milliseconds, a transaction has used, and on what line it was executed at. Reviewing these when developing code helps me to see if what I’m doing is going to cause an error.

Limits Class: In Apex, there is something called the Limits class, that allows a developer to check the usage of the limits without having to go and manually look through debug logs. With this class you can write methods such as: `Limits.getQueries()` and `Limits.getLimitQueries()` which will tell you information about your queries.

Salesforce Optimizer: A free tool that comes from Setup, that advises you on what to change and what you’re doing correctly/incorrectly to improve your Salesforce instance’s performance, including many other aspects. It’ll help with things such as triggers, and other things that could be sources of limit exceptions.

Event Monitoring (with the add-on): For bigger instances, the Event Monitoring tool will give you information about your API’s usage, Apex, and other things relevant to your organization to analyze and improve.

Looking through Debug Logs while reviewing code, instead of waiting for an exception to occur, is what I find to be the best way of identifying potential limit exceptions.

Salesforce Governor Limits:

Salesforce imposes various governor limits to ensure the efficient use of resources and to prevent abuse that could negatively impact the performance of the platform. Below is a comprehensive list of Salesforce governor limits:

CategoryLimitPurpose
Apex CPU Time10,000 milliseconds per transaction (synchronous)Controls the total execution time for all Apex code in a transaction.
SOQL Queries100 SOQL queries per transactionRestricts the number of queries to the database to prevent inefficient data retrieval.
SOSL Queries20 SOSL queries per transactionGoverns the number of Salesforce Object Search Language queries to the search index.
DML Statements150 DML statements (insert, update, delete, merge) per transactionEnsures that transactions don’t manipulate excessive records in a single operation.
Total Heap Size6 MB for synchronous Apex, 12 MB for asynchronous ApexRestricts the amount of memory (heap) that Apex code can use during execution.
Email Invocations10 email messages sent per transaction
Controls the number of email messages that can be sent in a single transaction.
Future Method Invocations50 future method invocations per transactionGoverns the number of asynchronous (future) methods that can be queued in a transaction.
Queueable Jobs50 Queueable jobs added to the queue per transactionRestricts the number of jobs that can be added to the queue for asynchronous processing.
Batch Apex100 batch jobs queued or active concurrentlyGoverns the number of batch jobs that can be processed concurrently.
Streaming API Events20,000 events per 24-hour rolling windowControls the number of Streaming API events that can be published within a specified timeframe.
Platform Events2,000,000 published events per rolling 24-hour windowGoverns the number of platform events that can be published within a specified timeframe.
Callouts100 callouts per transaction (synchronous), 200 callouts per transaction (asynchronous)Restricts the number of HTTP callouts that can be made in a single transaction.
External Services5,000 external service callouts per 24 hoursGoverns the number of callouts to external services via External Services in a specified timeframe.
Dynamic Apex500,000 characters for the total size of Apex codeRestricts the size of dynamically generated Apex code.
Push Notifications2,000,000 push notifications per rolling 24-hour windowGoverns the number of push notifications that can be sent within a specified timeframe.

Synchronous vs Asynchronous Apex: Why the Limits Differ

You’ll notice in the table above that limits like heap size and callouts have different thresholds depending on whether the code runs synchronously or asynchronously. This isn’t arbitrary — it reflects how each type of execution behaves.

Synchronous Apex (like a trigger firing when a user saves a record) has to complete immediately, while the user is waiting. Because of that, Salesforce keeps its resource ceiling comparatively tighter to avoid tying up shared infrastructure with long-running operations that block a user interface.

Asynchronous Apex — Future methods, Queueable Apex, Batch Apex, and Scheduled Apex — runs in the background in its own transaction, decoupled from any user waiting on a response. Since there’s no one staring at a loading spinner, Salesforce affords it more generous limits, like double the heap size and double the callout allowance.

This is a big part of why “use asynchronous processing” shows up so often as a best practice. If you’re working with large data volumes, complex integrations, or operations that naturally take longer to complete, shifting that logic into a Queueable or Batch Apex context often solves limit issues without touching your core logic much at all.

Conclusion

In conclusion, mastering the intricacies of Salesforce Apex Governor Limits is paramount for any developer aiming to create robust and efficient applications on the platform. As we’ve explored, these limits are in place to ensure the stability and performance of Salesforce environments, preventing resource abuse and optimizing overall system functionality. By understanding and navigating these limits judiciously, developers can strike a balance between innovation and adherence to best practices. Continuous monitoring, optimization, and leveraging Salesforce tools for performance analysis are essential components of successful development within the confines of Governor Limits. Ultimately, embracing these limits as guidelines rather than restrictions fosters the creation of scalable, reliable, and high-performing applications, enhancing the overall Salesforce development experience.

Get a Fast Estimate on Your Software
Development Project

Chat With Us

Frequently Asked Questions

Salesforce throws a runtime exception (typically a LimitException), and the entire transaction is rolled back. Unlike some exceptions, governor limit exceptions generally cannot be caught and continued past — the transaction fails as a whole.

Governor limits apply to the entire transaction, which means declarative automation like Flow and Process Builder consumes the same shared limits as Apex if they run within the same transaction context. A Flow that performs a DML operation inside a loop, for example, can hit the same limits as poorly bulkified Apex code.

Most per-transaction Apex limits are fixed and cannot be changed, regardless of edition or contract. Some platform-level limits (like API call allocations or storage) can sometimes be increased through Salesforce, but core execution governor limits are considered non-negotiable by design.

Yes. Writing test classes that insert bulk data (close to or at 200 records, matching Salesforce’s standard batch size) is one of the most reliable ways to catch bulkification issues before they reach production. Testing only with a single record is one of the most common reasons limit issues go unnoticed until they surface with real data.