Skip to main content
New tool CRON Expression Builder — preview next run times before you schedule Apex. Open the builder →
Diagram illustrating the difference between a Salesforce batch job stuck in queued status and a running job.
Apex

Salesforce batch job queued: Is it stuck or just scheduled?

A batch job sitting in queued status is stressful to look at, but it usually doesn't mean your code is broken. Here is why Salesforce shows that status for scheduled jobs, and where to find the real execution history.

The short answer

A scheduled Salesforce batch job with no end date stays in Queued status by design: the row stands for the recurring schedule, not for one run. To confirm the job is still executing, check the execution timestamps on the CronTrigger object.

Key takeaways Query the CronTrigger object and read PreviousFireTime and NextFireTime to confirm a scheduled job is still running. Use the AsyncApexJob table for errors and processed items, not as evidence of when the job last ran. Give every scheduled job a unique, descriptive name so you can find it in the CronTrigger table. Set an explicit end date when you schedule a batch job so the status updates cleanly once the schedule finishes. Log completions from the batch finish() method if you want a record that does not depend on the system tables.

Is your scheduled job actually stuck?

Have you ever opened your Apex Jobs page and felt that mini-panic when you see a Salesforce batch job queued for hours? It looks like the system is just ignoring your code. I've seen teams waste hours trying to "fix" a job that wasn't even broken in the first place. Most of the time, that "Queued" status is exactly what Salesforce is supposed to show.

In my experience this happens with jobs that were scheduled through the UI or via System.scheduleBatch without a specific end date. When you're managing asynchronous Apex in Salesforce, knowing how the platform tracks these jobs is the difference between a quick check and a long night of unnecessary debugging.

Why your Salesforce batch job queued status is misleading

When you schedule a batch job to run indefinitely, Salesforce creates a pointer in the system. It marks the job as "Queued" in the AsyncApexJob table to show that it's waiting for its next scheduled time, and it stays that way until the job actually fires or the schedule expires.

If you're looking for details on a specific run, you might try running a query like this:

SELECT ApexClass.Name, 
       Id, 
       JobItemsProcessed, 
       JobType, 
       Status, 
       NumberOfErrors, 
       CreatedDate, 
       CompletedDate 
FROM AsyncApexJob 
WHERE ApexClass.Name = 'YourBatchClassName' 
ORDER BY CreatedDate DESC

But if you see a Salesforce batch job queued here and the CreatedDate is from three days ago, don't assume it hasn't run since then. That row often represents the "schedule" itself, not the individual execution that happened this morning. This is one of the most confusing parts of the Salesforce UI for newer developers.

A dashboard mockup listing scheduled background jobs and their execution timestamps.

A dashboard mockup listing scheduled background jobs and their execution timestamps.

Using CronTrigger to solve the Salesforce batch job queued mystery

To know when your job actually ran last, look at the CronTrigger object. This is the source of truth for anything on a schedule. AsyncApexJob tells you what happened during the execution; CronTrigger tells you whether the engine is turning at all.

SELECT Id, 
       CronJobDetail.Name, 
       NextFireTime, 
       PreviousFireTime, 
       State 
FROM CronTrigger 
WHERE CronJobDetail.Name = 'YourScheduledJobName'

Look at the PreviousFireTime. If that timestamp matches your expected schedule, your job is running fine, even while the other table still shows the job as queued. It's also a good idea to keep an eye on your asynchronous Apex limits to make sure you aren't hitting any walls that would prevent the next run from starting.

When you schedule a job, give it a clear, unique name. If you just call it "Daily Batch," you'll have a nightmare of a time finding it in the CronTrigger table if you have multiple classes running on similar schedules.

How to fix a Salesforce batch job queued indefinitely

If you really want to avoid that confusing "Queued" state in your logs, the fix is simple: always set an end date. When a scheduled job has a defined end point, Salesforce handles the status updates more cleanly. Most of us need these jobs to run forever, though, and then you just have to get comfortable with the "Queued" status being the norm.

  • Check CronTrigger to see the NextFireTime.
  • Check AsyncApexJob only for errors and the number of items processed.
  • Use a custom logging object in your finish() method. Log every time a job completes and you don't have to rely on Salesforce's system tables at all.

Key takeaways

  • A queued status is often normal for a Salesforce batch job scheduled without an end date.
  • The AsyncApexJob table can be misleading; it often shows the status of the schedule, not the last run.
  • Always query CronTrigger to verify PreviousFireTime and NextFireTime.
  • Add a custom logging framework to track batch success and failure reliably.

Next time you see that "Queued" status, don't jump straight to aborting the job and rescheduling it. Run those two queries first. Most of the time you'll find everything is running exactly as it should, and you can get back to work that actually needs you.

Frequently asked questions

Why is my scheduled batch job stuck in Queued status?

A job scheduled indefinitely with no end date gets a pointer row in the AsyncApexJob table, and that row sits in Queued status while it waits for the next scheduled run. The status describes the active schedule, not a stalled execution.

How do you check if a scheduled batch job actually ran in Salesforce?

Query the CronTrigger object by job name and read the PreviousFireTime and NextFireTime fields. If PreviousFireTime matches the schedule you intended, the job engine is firing as it should.

How do you prevent a scheduled batch job from showing Queued indefinitely?

Give the job a defined end date when you schedule it through the UI or System.scheduleBatch. Salesforce updates the status more cleanly once a job with a fixed end point finishes its schedule.

Newsletter

One email every Tuesday

New guides, tool updates, and the release-note changes that break things.

No spam. Unsubscribe in one click.

Comments

Loading comments...

Leave a Comment