Have users of your application seen the “Unable to Process Request. Concurrent requests limit exceeded” error message and wondered why? (Hint: This limit is different than the concurrent API request limit.)  Do you know the common architectural decisions that can cause your requests to hit this limit?

In this blog post, we’ll discuss best practices that you can follow to improve the performance of your application and help you avoid this limit.

What the Concurrent Request Limit is and Why it Exists

The multitenant Force.com platform uses governor limits to ensure that system resources are available to all customers and to prevent any one customer from monopolizing them. If a governor limit is exceeded, the associated execution governor limit issues a runtime exception that cannot be handled. When you design your applications, you can help plan for their growth by keeping these limits in mind.

One of the limits customers frequently reach is the concurrent request limit. Once a synchronous Apex request runs longer than 5 seconds, it begins counting against this limit. Each organization is allowed 10 concurrent long-running requests. If the limit is reached, any new synchronous Apex request results in a runtime exception. This behavior occurs until the organization’s requests are below the limit.

Ultimately, this limit is in place to protect the user experience. Would you want your users waiting 5 seconds or more for a page to load?

What Counts Against the Limit

A single synchronous Apex request could include Apex code, SOQL, callouts, and triggers. You might need to tune these and other common components because the duration of their transactions counts toward the request limit.

Apex

Classes/controllers, triggers

SOQL

Web Services

External and Apex Web Services

Visualforce

ActionPoller, Ajax/ActionFunctions, JavaScript Remoting

API

Calls to an Apex Class

 

Bulk API, batch Apex, @future calls, scheduled Apex jobs, and SOQL-only API calls do not count against this limit.

How to Design to Avoid the Limit

Take the concurrent request limit into consideration as you design your application around your business processes. Does the business process need to be synchronous? Is batch processing possible? Can you use the Streaming API?

Web Services

The most common causes of limit errors are synchronous Web service callouts. When one of your application’s users submits an order, that business process depends upon one or more external Web services, which must finish running for your application to actually create the order. If these external Web services cannot scale to your expected volumes, consider alternative solutions, such as using a callback instead of waiting for the callouts to complete.

To use a callback, just continue to make the synchronous callout. The following steps complete automatically after that.

  1. The external Web service immediately returns an acknowledgement, saying that it received your request.
  2. After the external Web service processing completes, it calls an Apex Web service to update the appropriate data.
  3. The Streaming API publishes that updated data.

 

SOQL

The performance of your queries and DML operations is another big contributor to long-running requests. As your data grows, inefficient SOQL affects Visualforce pages, detail pages, list views and reports. If you’re querying for large amounts of data, you’ll incur additional processing time both when querying and rendering the data.

Refer to the Force.com Query Optimizer webinar for more information.

Data Skew

Data skew can also contribute to concurrent request limit errors. Consider the following scenario. You have a parent object with 10,000 or more child objects. Ordinarily, when you insert or change an owner of a child object, the Force.com platform automatically locks the parent for a certain amount of time. However, because you have data skew, the platform holds this lock even longer while determining the appropriate record access. The wait time for your lock is included in your total request time, and it causes your request to run for more than 5 seconds.

To avoid data skew so that you can also avoid ending up in this situation, read Reducing Lock Contention by Avoiding Data Skew.

Visualforce

With the ActionPoller component, you can poll by calling an Apex class.  Unfortunately, you can’t dynamically change the polling interval or condition. This can result in a large number of unneeded requests. If the polling operation is expensive and takes longer than 5 seconds, you’ll quickly hit the limit. For more scalable requests, use the Streaming API, not polling, to subscribe to near real-time notifications of changes to data.

The <Apex:ActionFunction> component provides support for invoking controller action methods directly from JavaScript code using an AJAX request. JavaScript remoting extends this capability and allows you to create pages with complex, dynamic behavior that isn’t possible with the standard Visualforce AJAX components. However, from an Apex perspective, both of these components are still synchronous requests that are similar to standard Visualforce requests, and they count toward your concurrency limit.

Summary

The concurrent request limit attempts to ensure a positive user experience by limiting the number of synchronous Apex requests running for more than 5 seconds. Once the limit is reached, new synchronous Apex requests are denied. This behavior can be disruptive to your work. Therefore, it is easier to avoid this limit when designing new applications than it is when tuning live applications. You can accomplish this goal by ensuring that your users’ workflows do not include synchronous requests that take longer than 5 seconds.

Some useful tips:

  1. Convert synchronous processes to asynchronous processes. Batch Apex might be a viable alternative. Limit synchronous Web service callouts.
  2. Use the Streaming API instead of polling
  3. Tune SOQL and DML operations. Make sure that your queries are selective. Limit the number of records in your list views. Avoid data skew.

 

Related Resources

About the Author and CCE Technical Enablement

John Tan is an Architect Evangelist within the Technical Enablement of the salesforce.com Customer-Centric Engineering group. The team’s mission is to help customers understand how to implement technically sound Salesforce solutions. Check out all of the resources that this team maintains on the Architect Core Resources page of Developer Force.

tagged , , , Bookmark the permalink. Trackbacks are closed, but you can post a comment.
  • Anshul Verma

    Nice article

  • http://twitter.com/TehNrd Jason Venable

    Does this limit apply to Apex methods that have the @ReadOnly annotation? I would think this is equivalent to an SOQL-only API call and therefore should not have this limit.

    • John Tan

      The limit will still apply with the @ReadOnly annotation. With SOQL-only API calls, you aren’t executing any Apex. However, the @ReadOnly annotation can be applied to a WS or an Apex class, which will still be executing Apex.