Our forward-looking statement applies to roadmap projections.
Asynchronous processing increases scalability by allowing higher limits per context. Asynchronous requests execute in their own threads behind the scenes, so users can continue to do work on the client side as the asynchronous tasks execute in the background.
Consider an asynchronous ordering process in Salesforce. When an order is saved, it triggers a message to an external warehouse management system with special instructions for how to pack and ship an item. The user who places the order doesn’t need an immediate response from the warehouse management system, so the request can be sent asynchronously. The asynchronous processing allows the user to continue their work without delays.
Three important considerations to keep in mind, however, are:
If you use the wrong tools or the wrong combinations of tools for the wrong jobs, unintended consequences that cancel out the benefits of asynchronous processing can occur. This guide provides explanations and recommendations, as well as potential drawbacks and anti-patterns for various asynchronous use cases, along with the rationale for those recommendations. It also provides insight into how various asynchronous implementation techniques operate and are regulated on the Salesforce Platform.
Note that this guide focuses exclusively on asynchronous processing within the Salesforce Platform. If you are looking for information about asynchronous integration patterns, check out Event-Driven Architecture.
This table outlines the tools that are available for asynchronous processing with Salesforce. Refer to this table to review each tool’s major characteristics during your decision-making process. This guide dives deeper into how to choose from these tools in the next sections.
| Product / Approach | Use Cases | Skills Required | Additional License Required |
|---|---|---|---|
| Apex Future Methods | We recommend that you use Queuable Apex instead of Apex future methods. Queueables have the same use cases as future methods but offer additional benefits. | Pro-code | No. Only certain license types count toward the daily asynchronous Apex execution limit. |
| Queuable Apex | Prefer this approach over future methods. Use for processes that involve long running database operations or external web service callouts. Queueable Apex offers additional benefits over future methods, including job IDs, support for non-primitive types, and job chaining. | Pro-code | No. Only certain license types count toward the daily asynchronous Apex execution limit. |
| Scheduled Apex | Execute Apex at a scheduled time defined by a cron expression. Although the act of scheduling Apex via the cron expression is an asynchronous process, the underlying code executes synchronously when the job starts. | Pro-code | No |
| Apex Continuation Callouts | Execute callouts from Apex methods running in a synchronous transaction context. | Pro-code | No |
| Platform Event Triggers | Loosely couple Salesforce with external systems and communicate between asynchronous components within the Salesforce Platform. | Low-code + Pro-code | Add-on required for high-volume platform event use cases |
| Change Data Capture | Capture and process change events asynchronously after the database transaction is committed. | Pro-code | Add-on license required to scale above baseline allocation. |
| Scheduled Path (After Commit Flows) | Execute at a dynamically scheduled time after a triggering event, such as when a record is created, updated, or deleted. | Low-code | No |
| Asynchronous Path (Record-Triggered Flows) | Execute an operation that you want to run on its own time. Avoid mixed DML errors that occur when you update a value on a related record that isn’t part of the record that triggered a flow. | Low-code | No |
| Outbound Messages | Share data with third party systems in near real-time via the SOAP protocol | Low-code | No |
| Email-to-Case | Automatically create cases and populate case fields based on values in incoming emails. | Low-code | No |
| Batch Apex | Build complex, long-running processes that involve thousands of records by dividing your record set and processing it in manageable chunks. | Pro-code | No. Only certain license types count toward the daily asynchronous Apex execution limit. |
| Scheduled Flows | Execute a flow in the background at a specified time and at a repeated frequency (daily, weekly, or once) to perform actions on a batch of records. | Low-code | No |
| Bulk API | Insert, update, upsert, query, or delete many records asynchronously and process the results later. | Pro-code | No |
| Lightning Actions | Allow Lightning pages to interact with the server without forcing users to fully refresh the page. | Low-code | No |
| Visualforce JavaScript Remoting (Legacy)* | Decouple Visualforce pages from their Apex controllers so that users can perform tasks without having to reload the entire page. | Pro-code | No |
| Salesforce Dashboards | Create visual displays of data from Salesforce reports | Low-code | No |
| CRM Analytics | Explore and visualize CRM data interactively. | Low-code | Yes |
| *Visualforce is no longer the preferred method for building custom UX components in Salesforce, as the Lightning Component framework offers greater flexibility. | |||
This table contains an overview of points to consider as you decide which asynchronous tool to use.
| Skills Required | Some of the tools outlined in this guide require code, while others can be configured declaratively. As you consider your options, think about the skillsets that your team members have. Keep in mind that even if developers are available for your initial implementation (through an implementation partner, for example), you may need to modify your solutions in the future. If your maintenance team lacks developers, a low-code option can be a better fit. |
| Asynchronous with Respect to Client | Determine whether client-side code is executed asynchronously within a browser or mobile app. Remember that even if code executes asynchronously on the client side, there’s a possibility that requests are serialized and executed synchronously on the server side. As you design your solutions, consider how processing is handled on both sides. Make sure that you don’t introduce any unintended bottlenecks. |
| Asynchronous with Respect to Server | Determine whether server-side processing is handled asynchronously within the Salesforce Platform. Keep in mind that asynchronous patterns don’t have SLAs. If you design processes that require a user to receive a response before they can continue with their work, then a tool that processes information synchronously is probably a better fit. |
| Type of Platform Limits Enforced | Determine the type of limits that apply to the execution. As you design your solutions, think carefully about how the volume and frequency of transactions affects the number of SOQL queries that the system needs to execute. Calculate the amount of processing time that each transaction requires and the amount of memory that the system needs to complete the execution. Make sure that the calculated values fall within the limits associated with your selected tools. |
When you select a tool for server-side asynchronous processing, first evaluate your organization’s requirements and available resources. Your goal is to select the tool or tools that minimize implementation and maintenance costs, but still ensure scalability and minimize your likelihood of limit violations. This goal is dependent on the technical considerations outlined in the next sections, as well as the makeup of your team. For example, consider whether you have Apex developers on your team who can maintain your pro-code solution. Otherwise, a declarative approach can make more sense. . Also, keep in mind that different sets of limits can apply to different tools.
Questions to ask:
The Salesforce Platform’s multitenant architecture isolates and concurrently supports the varying requirements of many tenants (orgs). All asynchronous Apex methods covered in this guide are executed within the same asynchronous infrastructure in the Salesforce Platform. They use a message queueing framework that is governed by two primary enforcement mechanisms: flow control and fair usage.
The flow control and fair usage mechanisms prevent a single tenant from using too many server resources and not leaving enough resources for the remaining tenants. Although it’s helpful to understand how these mechanisms work, your key takeaway should be that following asynchronous processing best practices, such as the ones outlined in the next sections, significantly reduces your likelihood of running into issues with them.
The platform’s flow control mechanism prevents one org from flooding a given message type, which consumes too many threads and negatively affects other orgs. Before the framework adds new entries to the queue associated with a message type, it checks the first several thousand existing entries in the queue. If the majority of existing entries are associated with that same sorg and that org already also has entries in worker threads, then the newly added entries are moved to the back of the queue. This process is called re-enqueuing. Re-enqueuing typically happens to Batch Apex and Bulk API processes because they often insert large numbers of entries into their queues at the same time.
The platform’s fair usage mechanism implements a tier-based system. The system ensures that each org on the Salesforce Platform gets a fair share of processing time for a given message type, including Future, Queueable, and Batch message types. If one org dominates a given message type during the same time that other orgs are waiting to perform work on the same message type, the fair usage algorithm reduces the number of threads that the org has available for that particular message type.
See Fair Usage Mechanism.
A benefit of using asynchronous Apex methods is that some governor limits, such as SOQL query limits and heap size limits, are higher. However, don’t rely too heavily on these methods. Due to the finite resources allocated to asynchronous infrastructure, heavy usage of Future, Queueable, and Batch Apex can cause processing delays that stem from limitations based on fair usage and flow control.
Outbound callouts that use asynchronous Apex count against the asynchronous Apex limit. The daily limit is currently 250,000 or 200 times the number of applicable user licenses, whichever is greater. This limit can be an issue for high-volume use cases. If you exceed the limit, your asynchronous Apex jobs and their associated outbound callouts will fail.
Additionally, because the platform has a finite number of asynchronous threads available, outbound integrations via asynchronous Apex have limited scalability. Any high-volume outbound integrations that exceed the number of available threads can have long processing times and lead to delays.
For high-volume use cases, consider these alternative approaches. API calls with these approaches count towards the daily API request limit, which is significantly higher than the daily asynchronous Apex limit. Thus, these approaches are more scalable. Note, however, that there are still physical limitations on the number of concurrent requests that any CPU can process.
See Middleware Scheduled Pull.
See Middleware Pull via Platform Event Notification.
| Product / Approach | Use Cases | Skills Required | Asynchronous with Respect to Client | Asynchronous with Respect to Server | Type of Platform Limits Enforced |
|---|---|---|---|---|---|
| Apex Future Methods | We recommend that you use Queuable Apex instead of Apex future methods. Queueables have the same use cases as future methods but offer additional benefits. | Pro-code | Yes | Yes | Asynchronous |
| Queueable Apex | Prefer this approach over future methods. Use for processes that involve long running database operations or external web service callouts. Queueable Apex offers additional benefits over future methods, including job IDs, support for non-primitive types, and job chaining. | Pro-code | Yes | Yes | Asynchronous |
| Scheduled Apex | Execute Apex at a scheduled time defined by a cron expression. Although the act of scheduling Apex via the cron expression is an asynchronous process, the underlying code executes synchronously when the job starts. | Pro-code | Yes | Yes | Synchronous |
| Apex Continuation Callouts | Callouts from Apex methods running in a synchronous transaction context | Pro-code | Yes | Yes | Synchronous |
Queuable Apex With Queuable Apex, you can run Apex processes that involve extensive database operations or external web service callouts asynchronously. To use Queuable Apex, implement the Queueable interface, and then add a job to the Apex job queue. This approach ensures that the asynchronous Apex job runs in the background in its own isolated thread and doesn’t delay the execution of your main Apex logic. Each queued job runs when system resources become available.
Queueable Apex represents the evolution of asynchronous Apex. It offers features that aren’t available to Apex future methods, including:
Salesforce uses a queue-based framework to handle asynchronous processes. This queue is used to balance request workloads across orgs. To ensure that your org uses this queue as efficiently as possible:
Use scheduled Apex to execute at a specified time and at a repeated frequency as defined by a cron expression. Although the act of scheduling Apex via the cron expression is an asynchronous process, the underlying code executes synchronously when the job starts. Scheduled Apex is ideal for daily or weekly maintenance tasks.
Historically, synchronous callouts made from an Apex method running in a synchronous Apex transaction context, such as a Visualforce controller or a Lightning component controller, were subject to the Apex concurrency limit regarding long-running requests. As of Winter ’19, synchronous callouts are no longer counted as long-running. Although Apex continuations were initially created as a solution to synchronous callouts that resulted in long-running requests, they also provide some additional benefits.
Although continuations execute asynchronously with respect to the originating synchronous action, there are key differences between Apex Continuations and other asynchronous Apex techniques such as future methods, Queueable, or Batch. Key differences are:
Platform events are the Salesforce Platform’s implementation of a purely event-driven architecture. You can find more details about the components associated with this type of architecture in the Architect’s Guide to Event-Driven Architecture.
Platform events and platform event triggers/flows are often great alternatives to running asynchronous Apex. They’re also a great way to invoke off-platform processing. For example, you can use a combination of Amazon Web Services (AWS) event relays and platform events to invoke serverless compute functionality in AWS Lambda. Work that’s being performed relatively quickly and without any callouts (which aren’t possible from a platform event trigger or flow), is a great candidate for a platform event/trigger or event/flow combination.
See Asynchronous Processing via Platform Events.
The events published to the bus via publish after commit are delivered in order and can be bulk processed by the trigger or flow in a separate synchronous context. The context is synchronous and enforces all synchronous governor limits. Choose the platform event trigger/flow batch size carefully to avoid hitting limits.
| Product / Approach | Use Cases | Skills Required | Asynchronous with Respect to Client | Asynchronous with Respect to Server | Type of Platform Limits Enforced |
|---|---|---|---|---|---|
| Platform Event Triggers | Loosely couple Salesforce with external systems and communicate between asynchronous platform components. | Low-code + Pro- code | Yes | Yes | Synchronous |
It’s helpful to use Publish Immediately for use cases such as logging, where you want to publish the logging event regardless of whether the transaction succeeds and commits, or fails and rolls back. It’s possible to immediately publish a platform event that’s consumed by a platform event trigger. The platform event trigger then competes for a database row lock with the transaction that published it. Review all designs thoroughly prior to immediately publishing platform events to ensure that you avoid this scenario.
Asynchronous flows provide low-code alternatives to asynchronous Apex. As with other forms of asynchronous processing, they execute in the background when resources are available. Asynchronous flows also have no SLAs and can have unpredictable wait times.
| Product / Approach | Use Cases | Skills Required | Asynchronous with Respect to Client | Asynchronous with Respect to Server | Type of Platform Limits Enforced |
|---|---|---|---|---|---|
| Scheduled Path (After Commit Flows) | Execute at dynamically scheduled times after triggering events. | Low-code | Yes | Yes | Asynchronous |
| Asynchronous Path (Record-Triggered Flows) | Execute an operation that you want to run on its own time and to avoid mixed DML errors. | Low-code | Yes | Yes | Asynchronous |
Scheduled Paths are cron trigger-based to execute at a specific time. They execute when records are created, updated or deleted and give you granular control over when to run the automation relative to the record change. (Example: send an email to a user one hour before a task is due.) Unlike Apex future methods, which are limited to a maximum of 50 methods enqueued in a synchronous transaction, scheduled flow actions don’t currently have a max enqueue limit per transaction. There is, however, a batch size configuration within the definition of the scheduled path that allows for some control over how many records are handled by the scheduled path flow execution.
Asynchronous Paths can be added to record-triggered flows. They run in the background and don’t delay the execution of the transaction that originally triggered the flow. You can use an asynchronous path to execute a long-running operation or any operation that you want to run on its own time. Asynchronous paths can help avoid mixed DML errors that occur when you need to update a value on a related record that’s not part of the record that triggered the flow.
Note: Outbound messaging is a legacy feature and platform events (described in the previous section) are a more modern approach and offer greater flexibility. Platform Events are Salesforce’s recommended pattern for Event Driven Integration.
Outbound messages provide a means of asynchronous outbound communication via SOAP API. When configured in Salesforce, the outbound message definition produces a SOAP WSDL that can be consumed by an external web service provider. Outbound messages can be triggered from workflow rules, Process Builder processes, or Lightning after-save flow triggers. An outbound SOAP message can contain up to 100 notifications. Each notification contains the object ID and a reference to the associated sObject data. If the information in the underlying object changes after the notification is queued but before it is sent, only the latest data is delivered and not the intermediate changes.
| Product / Approach | Use Cases | Skills Required | Asynchronous with Respect to Client | Asynchronous with Respect to Server | Type of Platform Limits Enforced |
|---|---|---|---|---|---|
| Outbound Messages | Share data with third party systems in near real time via the SOAP protocol | Low-code | N/A | Yes | N/A |
When an outbound message listener (the web service you configured with the generated WSDL) receives a message, it uses the included session ID information to call the Lightning Platform API to update the record in Salesforce that triggered the outbound message.
| Product / Approach | Use Cases | Skills Required | Asynchronous with Respect to Client | Asynchronous with Respect to Server | Type of Platform Limits Enforced |
|---|---|---|---|---|---|
| Email-to-Case | Automatically create cases and populate case fields based on values in incoming emails. | Low-code | Yes | Yes* | Synchronous |
| * Email-to-Case is handled as both sync and async, but with synchronous Apex limits | |||||
Email-to-Case normally works in a synchronous manner. There’s a limit of four synchronous threads to handle inbound Email-to-Case requests. The synchronous form of the handler maintains a connection to the inbound Salesforce mail server (MTA) that receives the email. However, there are reasons why Email-to-Case can be handled asynchronously:
To process large volumes of records asynchronously, consider using one of these approaches.
| Product / Approach | Use Cases | Skills Required | Asynchronous with Respect to Client | Asynchronous with Respect to Server | Type of Platform Limits Enforced |
|---|---|---|---|---|---|
| Batch Apex | Complex, long-running processes that involve thousands of records | Pro-code | Yes | Yes | Asynchronous |
| Schedule-Triggered Flows | Perform actions on a batch of records in the background at a specified time and at a repeated frequency via a flow. | Low-code | Yes | Yes | Synchronous |
| Bulk API | Insert, update, upsert, query, or delete many records asynchronously. | Pro-code | Yes | Yes | Asynchronous |
You can use Batch Apex to build complex, long-running processes that involve thousands of records. Batch Apex operates by dividing up your record set and processing it in manageable chunks. As an example, you can build an archiving solution that runs on a nightly basis and adds records older than a certain date to an archive. Or you can build a data cleansing operation that looks at all Accounts and Opportunities on a nightly basis and performs any necessary updates based on a set of predefined criteria.
A schedule-triggered flow is a flow scheduled to execute at a specified time and at a repeated frequency (daily, weekly, or once) to perform actions on a batch of records. (Example: update a field in all cases with a status of "Open" at 2am every night.) Scheduled Flows are executed via the cron trigger mechanism and are bulk processed.
Bulk API is based on REST principles and is optimized for working with large sets of data. You can use it to insert, update, upsert, query, or delete many records asynchronously and process the results later. The Salesforce Platform processes the request in the background. In contrast, SOAP API and REST API use synchronous requests and are optimized for real-time client applications that update a few records at a time. You can use both of these APIs for processing many records, but when the data sets contain hundreds of thousands of records, they are less practical. Bulk API’s asynchronous framework is designed to make it simple and efficient to process data from a few thousand to millions of records.
The easiest way to use Bulk API is to enable it for processing records in Data Loader using CSV files. With Data Loader, you don’t have to write your own client app. Sometimes, though, unique requirements necessitate writing a custom app.
There are two Bulk APIs available within the Salesforce Platform.
For more information on API limits, see Bulk API Limits and Bulk API 2.0 Limits.
Although Salesforce handles the majority of asynchronous requests on the server side, tools that support asynchronous processing on the client side are also available. Client-side asynchronous processing is subject to the limitations of the browser or the mobile application within which it is executing.
Questions to Ask:
| Product / Approach | Use Cases | Skills Required | Asynchronous with Respect to Client | Asynchronous with Respect to Server | Type of Platform Limits Enforced |
|---|---|---|---|---|---|
| Lightning Actions | Allow Lightning pages to interact with the server without full page refreshes | Low-code | Yes | No | Synchronous |
| Visualforce JavaScript Remoting (legacy)* | Allow Visualforce pages to interact with the server without full page refreshes | Pro-code | Yes | No | Synchronous |
| *Visualforce is no longer the preferred method for building custom UX components in Salesforce, as the Lightning Framework offers greater flexibility | |||||
All Lightning communications from the browser to the Salesforce Platform take the form of XMLHttpRequest (XHR) requests. This allows Lightning pages to interact with the server without having to fully refresh the page. Each of these actions results in a synchronous transaction context on the Salesforce Platform.
Lightning applications involve frequent communication to the Salesforce Platform to support the Lightning Framework. To support this, multiple requests can be issued at the same time, or “boxcar’ed” in a single XHR request to the Salesforce core platform. The maximum boxcar limit for Lightning is 2500 maximum actions per request. However, each of the boxcars within a request will be processed serially and in order in a separate transaction context. For example, if 100 custom Apex Lightning actions are boxcar’ed together and each takes four seconds to run, 100 separate Apex transactions will be executed on the Salesforce Platform under the same request, taking a total of 400 seconds to complete. In the browser, there would be a single XHR request issued that would take 400 seconds before a response was received.
See Boxcar’ing in Lightning Actions.
If you are building an application that uses polling or timers, you should wrap any code that modifies a component outside the normal rerendering lifecycle in $A.getCallback(). This will ensure that the framework will rerender the modified component and processes any enqueued actions right away. Not taking this approach can cause actions to be queued up indefinitely until a callback is requested through a different process (for example, a user returns to their desk and performs some other action in the system), which will send all of the queued up actions to the server simultaneously in transactions that have very high numbers of boxcars.
Note: Visualforce is no longer the preferred method for building custom UX components in Salesforce, as the Lightning Framework (described in the previous section) offers greater flexibility. However, you may still encounter Visualforce pages in existing implementations.
JavaScript remoting is a tool that front-end developers can use to make an Ajax request from a Visualforce page directly to an Apex controller. JavaScript remoting allows you to run asynchronous actions by decoupling the page from the controller and performing tasks on the page without having to reload the entire page. This helps alleviate view state issues while still executing in the context of the user viewing the page. JavaScript remoting also allows you to ensure that you’re passing only the data that you need each time that you make a call.
Multiple JavaScript remoting requests can be issued at the same time by boxcar’ing them in a single HTTP request to the Salesforce core platform. On the platform, each of the boxcars (i.e. a separate JavaScript remoting action) will be processed serially and in order in a separate Apex synchronous transaction context. For example, if 10 remoting actions were boxcar’ed together and each took four seconds to run, 10 separate Apex transactions would be executed on the Salesforce Platform under the same request, taking a total of 40 seconds to complete. There would be a single request issued in the browser that would take 40 seconds before a response was received.
See Boxcar’ing in JavaScript Remoting.
| Product / Approach | Use Cases | Skills Required | Asynchronous with Respect to Client | Asynchronous with Respect to Server | Type of Platform Limits Enforced |
|---|---|---|---|---|---|
| Salesforce Dashboards | Create visual displays of data from Salesforce reports. | Low-code | Yes | Yes | Asynchronous* |
| CRM Analytics | Explore and visualize CRM data interactively. | Low-code | Yes | Yes | Asynchronous |
| *Dashboards execute asynchronously and are subject to the same fair usage and flow control limits as asynchronous Apex message types. | |||||
Unlike reports that run directly via the UI or API, dashboard-based reports execute asynchronously and are subject to both fair usage and flow control limitations. Dashboard-executed reports map into four separate asynchronous message queues for the reports: SMALL, MEDIUM, LARGE, and UNKNOWN. When a dashboard is refreshed, the reports underlying the dashboard panels are submitted to the various dashboard message queues. As the reports complete execution, the various dashboard panels render in the UI.
Reports used for dashboards must follow all report performance best practices. If any of the reports that a dashboard executes time out during execution, the dashboard status remains stale. When a user lands on a stale dashboard, the reports are automatically resubmitted to the message queues to execute. This can lead to message queue thread starvation of other message types due to overwhelming volumes of dashboard report message types.
There are four scenarios where asynchronous processing occurs within CRM Analytics:
All of the processes mentioned above utilize Bulk API in the background, but instead of being subject to Bulk API’s limits, they are subject to CRM Analytics Limits. Keep these limits in mind when working with large data volumes in CRMA.
Because asynchronous processing happens in the background, any failures that occur typically aren’t reported in the UI. Additionally, while rare, the platform’s flow control mechanism or fair usage algorithm can determine that asynchronous jobs must be put on hold to ensure platform stability. This hold can create scenarios where synchronous processes attempt to perform CRUD operations on records that should already have been updated by asynchronous processes that haven’t run yet.
These issues make monitoring and alerting for asynchronous processes critical. Monitoring and alerting enables you to detect issues quickly and either fix them on your own or reach out to Salesforce for assistance. They represent a cost-effective failure mitigation or risk management strategy so your asynchronous processes remain highly available.
You may have seen guidance on third-party sites for designing custom monitoring and alerting solutions. Their approaches often require you to generate error logs when Apex code is executed, and then insert the logs into a custom object or a big object. We don’t recommend this approach for these reasons.
Take some time to explore all available monitoring and debugging options on the platform before opting to use custom error logging as your primary monitoring and alerting solution. Instead, consider these two alternative approaches.
If you want to build your own monitoring and alerting solution, you can write SOQL queries against the AsyncApexJob object to check the status of:
With this approach, you can design a UI component that allows users to execute a query and view the results on demand, or you can build a background job that executes the query periodically and sends alerts if it detects any anomalies.
See Asynchronous Apex Monitoring via Custom Query.
Here are some considerations to keep in mind with this approach.
Proactive Monitoring allows you to receive performance and dequeue latency alerts that get triggered during the execution of asynchronous processes. System administrators can elect to receive notifications via email, review past alert trends in a self-service portal on Salesforce Help, and in specific critical scenarios, alerts can also automatically create Salesforce support cases, which will greatly reduce our support team’s time to detect (TTD) and time to engage (TTE). This feature requires a Signature Success Plan.
Refer to this guide when building or considering asynchronous processing on the Salesforce Platform. It’s always a good idea to understand the full scope of options available to you, and how they may fit with your specific use case. Be sure to thoroughly assess your current landscape before making changes to any of your existing architectures, especially if your current solution is working well.
Help us make sure that we’re publishing what is most relevant to you. Take our survey to provide feedback on this content, and tell us what you want to see next.