1

I recently ran into a strange issue with the 50,000 row query limit that had me puzzled due to the belief that the 50,000 row query limit applied only per-call.

This realization occurred while writing a LWC where the .js file calls apex methods to gather data. Specifically, in this instance, I was creating a custom table that displays some aggregated data and only loads and displays 5 rows at time. Users can page through the table to load and display 5 more items.

Whenever I am loading a table page, the JS side makes 5 separate calls (one for each row) to the same APEX method to gather all the aggregated data. I actually use a Promise to send off all 5 calls at one time.

Inside of this reused APEX method is a few queries that get about 2500 rows combined MAX. This apex method does not query over 2500 rows per-call in any case.

When JS uses a promise to send off 5 of these calls at once, I have no problem. However, I also allow users to download the entire table into a csv. When they hit this button, JS uses the same APEX method to load the data, but this part requires JS to put more than 5 calls to the same method in the Promise that gathers all the data. If the table is 10 pages, it ends up putting 50 calls to the same APEX method in the same promise. This is when I get the 50,000 query limit reached error.

This has me confused because I thought that a single call to an APEX method can't query over 50,000 rows... After playing around a little, I noticed that the error would occur once I tried to load more than 20 rows. 19 rows worked fine because 19 * 2500 < 50,000. But 21 rows errored because 21* 2500 > 50,000.

Therefore, I believe that the 50,000 query limit isn't calculated per APEX Method call, but rather calculated on the total number of simultaneous calls to the same APEX method.

6

Aura, and LWC, groups several requests together in order to maximize performance. This is called "boxcar'ing" (or boxcarring) in the documentation. All Apex requests in the same boxcar payload are subject to a single set of governor limits, even though they're allowed to fail/succeed independently. This means you need to make sure you don't place DML before callout operation requests, and you'll want to limit the number of requests you perform simultaneously. This is documented behavior and has existed since the beginning of Lightning.

|improve this answer|||||
  • Interesting. Up until now, everything I've read about the 50,000 query limit suggests it's per-call. I've never read about Lighting "boxcaring" until now. thanks – BlondeSwan Jul 24 '19 at 15:36
  • 1
    @BlondeSwan I think its from VF days. It was called as buffer in remoting . Whether to group requests executed close to each other in time into a single request. The default is true. – Pranay Jaiswal Jul 24 '19 at 15:39
  • 5
    In a call I had with one of the Salesforce Product Managers (responsible for LWC boxcarring) where I was asking about the ability to turn off boxcarring IN LWC (no, you can't and there's nothing yet on the cards), she admitted that the limit being applied across all the requests in the boxcarred chain is a bug that they are looking to fix (usual "forward statement" declaration applies). Once fixed, each request will have its own independent limits again. – Phil W Jul 24 '19 at 15:58
  • @PhilW Good to know. I always felt it was a bug (undocumented behavior). At least they know about it. – sfdcfox Jul 24 '19 at 16:06
3

Its called as boxcarring, Salesforce bundles multiple request in to 1 to save repeated calls to server.

You can seee from Debug logs, only one is created.

A quick solution is to add a timeout or use the promise chain while calling apex. In this way , each apex call will be treated as new transaction and those limits get reset.

new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000); // (*)

}).then(function(result) { // (**)

  alert(result); // 1
  return result * 2;

}).then(function(result) { // (***)

  alert(result); // 2
  return result * 2;

}).then(function(result) {

  alert(result); // 4
  return result * 2;

});

Box carring also has side-effect of slowing initial loading down. read more here.

Winter 20 Update: Starting winter 20, the batched group wont have to share limits , each individual action in the group will have its own set of limits.

More here: https://releasenotes.docs.salesforce.com/en-us/winter20/release-notes/rn_lc_predictable_apex_limits.htm

|improve this answer|||||
  • There's a lot of discussion about staggering the requests by introducing various delays elsewhere on SFSE where the conclusion was it more-or-less worked but could require significantly long delays (of the order of half a second) in order to avoid boxcarring. – Phil W Jul 24 '19 at 16:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.