Not verified hands-on. This article was written from primary documentation rather than reproduced in an org, so it carries no tested-release badge. If you run it and something differs, say so in the comments and it gets tested and corrected.

Your org gets 250,000 asynchronous Apex executions per rolling 24 hours, or 200 times your user licence count, whichever is higher. Batch Apex counts one execution per execute chunk rather than one per job, which is why a single badly-scoped batch can spend a meaningful share of the day’s budget on its own. Check consumption in Setup before you assume you have headroom.

What counts, and what does not

Counts toward the limit Does not
Each @future method invocation Synchronous Apex of any kind
Each Queueable job execution Flow runs that stay synchronous
Each Batch Apex execute chunk Platform event subscriptions
Batch start and finish methods API calls (separate limit)
Each scheduled job firing Reports and dashboards

The batch arithmetic is the part that catches teams out. A batch over 5,000,000 records at the default scope of 200 is 25,000 execute calls, plus start and finish — a tenth of the default allowance from one job. Drop the scope to 10 because of a callout and the same job becomes 500,000 executions, which is more than the entire daily budget.

Working out your actual number

The formula is 250,000 or 200 × the number of user licences, whichever is greater. Only full Salesforce user licences count toward the multiplier in the usual case — platform and community licences are counted differently, so do not assume a large community population raises your ceiling.

Licences 200 × licences Your limit
200 40,000 250,000
1,250 250,000 250,000
5,000 1,000,000 1,000,000

Below about 1,250 licences the multiplier is irrelevant and everyone gets the same 250,000. Most orgs that hit this limit are not large. They are ordinary orgs with one job doing something inefficient.

It is a rolling 24 hours, not a calendar day

There is no midnight reset. The platform looks back 24 hours from now, which means a job that consumed the budget at 3pm yesterday is still holding it at 2pm today. Recovery is gradual as old executions age out, so an org that blew the limit does not come back all at once. It comes back in a slow trickle that looks like intermittent failure.

That is also why “we’ll just rerun it tomorrow morning” often fails again.

What failure looks like

You do not get a clean exception in your code. Jobs stop being accepted: System.enqueueJob throws, Database.executeBatch throws, and @future calls fail with a message about the limit having been exceeded. Because most orgs call these from triggers, the visible symptom is users unable to save records for reasons that have nothing to do with what they are saving.

Scheduled jobs are worse: a scheduled job that cannot start does not retry, so the nightly run is simply missing.

Finding out where it is going

Setup → System Overview shows async Apex usage against the limit. It is a blunt instrument but it answers “are we close” in one screen.

For attribution, query the job records:

SELECT ApexClass.Name, JobType, Status, COUNT(Id) total
FROM AsyncApexJob
WHERE CreatedDate = LAST_N_DAYS:1
GROUP BY ApexClass.Name, JobType, Status
ORDER BY COUNT(Id) DESC

Remember that one AsyncApexJob row for a batch represents many executions, so read TotalJobItems on batch rows rather than counting rows:

SELECT ApexClass.Name, TotalJobItems, JobItemsProcessed, NumberOfErrors, Status
FROM AsyncApexJob
WHERE JobType = 'BatchApex' AND CreatedDate = LAST_N_DAYS:1
ORDER BY TotalJobItems DESC

TotalJobItems is the chunk count, and therefore the execution count. Sorting by it usually identifies the culprit in one query.

Reducing consumption

Raise the batch scope. The single highest-value change. Moving from 200 to 2,000 cuts executions by 90%. You can only do this if each chunk stays inside per-transaction limits, which is exactly the tradeoff. Bigger chunks use fewer executions and more heap and CPU per chunk.

Filter in start, not in execute. A batch whose query returns every record and then skips 95% of them in execute is paying full price for nothing. Put the condition in the QueryLocator.

Batch the work, not the record. A trigger that enqueues one Queueable per record generates 200 executions per save. Collect the Ids and enqueue one job for the batch.

Stop scheduling jobs that usually do nothing. A job running every 15 minutes is 96 executions a day whether or not there is work. Hourly is 24. Match the frequency to how often the data actually changes.

Use platform events for fan-out. Event subscriptions are governed separately, so moving genuinely event-shaped work off async Apex takes it out of this budget entirely. You give up the ordering and transactional guarantees that a queueable chain gives you.

Frequently asked

Can Salesforce raise the limit?

It is not a standard adjustable limit, and the usual answer to a support case is to fix the consumption. Treat a request as a last resort after the scope and frequency changes above, and expect to show the job inventory.

Does a failed job still count?

Yes. An execution that throws has consumed an execution. A job that fails repeatedly and is retried by your own code consumes the budget faster than one that succeeds.

Do Queueable and Batch draw from the same pool?

Yes, along with future methods and scheduled jobs. There is no per-type sub-allocation, so reducing any of them helps all of them.

Does the limit apply in sandboxes?

Yes, and sandboxes typically have far fewer licences, so they hit the floor of 250,000 rather than a multiplier. A data-heavy job that is fine in production can exhaust a sandbox.

Is this the same as the concurrent job limit?

No. The limit here is executions per 24 hours. Separately, there is a ceiling on how many batch jobs run at once and how many can be queued, which is what makes jobs sit in Holding status rather than fail.


Reference: Execution Governors and Limits and Using Batch Apex, Salesforce Apex Developer Guide.