Skip to main content

SF-0371 · Scenario · Medium

Can we track the progress of the batch job?

✓ Verified by Vikas Singhal · Last reviewed 5/17/2026 · Updated for Spring '26

Yes — every batch job is represented by an AsyncApexJob record. You can monitor progress through the Setup → Apex Jobs UI or query the record directly with SOQL.

The JobId is your handle

Id jobId = Database.executeBatch(new MyBatch(), 200);

That JobId is the primary key into AsyncApexJob. Save it, log it, surface it to the user — anywhere you need to refer to “that specific run.”

Useful fields to query

SELECT Id, ApexClass.Name, Status, JobType,
       TotalJobItems, JobItemsProcessed, NumberOfErrors,
       ExtendedStatus, CreatedDate, CompletedDate, CreatedBy.Email
FROM AsyncApexJob
WHERE Id = '7071g00000abcde'
FieldMeaning
StatusQueued, Preparing, Processing, Completed, Failed, Aborted
JobTypeBatchApex, BatchApexWorker, Future, Queueable, ScheduledApex
TotalJobItemsTotal number of chunks (e.g. 50 for 10,000 records / chunk of 200)
JobItemsProcessedNumber of chunks completed so far
NumberOfErrorsCumulative errors across all chunks
ExtendedStatusLast error message, if any
CreatedDateWhen the job was enqueued
CompletedDateWhen it finished, or null if still running

JobItemsProcessed / TotalJobItems is your progress percentage.

Build a status helper

public class BatchMonitor {
    public class BatchStatus {
        public String status;
        public Integer percent;
        public Integer errors;
        public String error;
    }

    public static BatchStatus check(Id jobId) {
        AsyncApexJob job = [
            SELECT Status, TotalJobItems, JobItemsProcessed,
                   NumberOfErrors, ExtendedStatus
            FROM AsyncApexJob WHERE Id = :jobId
        ];
        BatchStatus s = new BatchStatus();
        s.status = job.Status;
        s.percent = (job.TotalJobItems > 0)
            ? (job.JobItemsProcessed * 100 / job.TotalJobItems)
            : 0;
        s.errors = job.NumberOfErrors;
        s.error = job.ExtendedStatus;
        return s;
    }
}

A Lightning component can call this every few seconds to render a progress bar.

Where to look in the UI

PageWhat you see
Setup → Apex JobsAll async jobs (batch, future, queueable, scheduled), most recent first
Setup → Apex Flex QueueBatch jobs in Holding status waiting for a slot
Setup → Scheduled JobsSchedulable invocations on a cron schedule

The Apex Jobs page links to per-job detail with chunk-by-chunk error messages.

What “Completed” doesn’t mean

A status of Completed only means the job finished its lifecycle. Some chunks may have failed — check NumberOfErrors. A defensive monitoring check:

AsyncApexJob job = [SELECT Status, NumberOfErrors FROM AsyncApexJob WHERE Id = :jobId];
Boolean fullSuccess = (job.Status == 'Completed' && job.NumberOfErrors == 0);

Errors in detail

AsyncApexJob.ExtendedStatus shows the last error message. To see all error messages with their records, query BatchApexErrorEvent (a Platform Event) or attach a custom error log inside your batch’s execute:

catch (Exception e) {
    insert new Batch_Error__c(
        Job_Id__c = ctx.getJobId(),
        Message__c = e.getMessage(),
        Stack_Trace__c = e.getStackTraceString()
    );
}

Common interview follow-ups

  • Are jobs deleted from AsyncApexJob? — Yes, after 7 days. For longer audit, log your own records.
  • Can a user without admin see Apex Jobs? — Needs View Setup and Configuration + Author Apex depending on what they need to see.
  • How fast is the status updated? — Near real-time; JobItemsProcessed increments as chunks complete.

Verified against: Apex Developer Guide — Monitoring Asynchronous Apex. Last reviewed 2026-05-17.