I am looking for some advice regarding the optimization of an Apex Batch which is behaving quite differently in
In our ORGs we have a Batchable process that is responsible for fetching data from different sObjects (all of them using a filter on a Lookup field, thus being indexed), sending that data to an external endpoint, and ultimately delete records.
While testing it on a
UAT environment the callout times are quite fast (
40/50ms), the batch scope can be set as
200 and the whole process works as expected.
However, while trying to run it on
PROD the performance is heavily degraded (callout time increases to
9000ms), no more than 10 records can be modified on each scope and overall each transaction takes around 3 minutes to be completed.
There are some differences between the environments, the most important ones IMO being:
- The data volume is pretty much bigger in
PROD(We're fetching around
20Krecords on the QueryLocator but there are roughly 3 million records in total)
- Around 10 future calls are being made per minute (while the batch is also processing);
I tested invoking the
PROD endpoint outside of Salesforce (using Postman) with the same number of records on the payload which are being sent from Salesforce (10) and the response time varies between 12, 30, and 120 seconds (leading to a timeout, thus I am ruling that the issue is only related to Salesforce).
I used Query Planner to test the query used in the batch Start method, which I have attached to this post.
Although the issue might also be related to infrastructure on the endpoint side and we haven't run against any Non-selective query exception I would like to assure optimal performance on the Salesforce side. Would the data volume impact the overall callout time to an external endpoint?
I am running out of ideas to improve the batch. Would you advise any particular action here? Looking forward to discussing some ideas and let me know if it wasn't fully clear.
Best regards and thank you in advance!
PS.: Edited to include the Execution Overview Timeline after the initial comment: