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'
| Field | Meaning |
|---|---|
Status | Queued, Preparing, Processing, Completed, Failed, Aborted |
JobType | BatchApex, BatchApexWorker, Future, Queueable, ScheduledApex |
TotalJobItems | Total number of chunks (e.g. 50 for 10,000 records / chunk of 200) |
JobItemsProcessed | Number of chunks completed so far |
NumberOfErrors | Cumulative errors across all chunks |
ExtendedStatus | Last error message, if any |
CreatedDate | When the job was enqueued |
CompletedDate | When 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
| Page | What you see |
|---|---|
| Setup → Apex Jobs | All async jobs (batch, future, queueable, scheduled), most recent first |
| Setup → Apex Flex Queue | Batch jobs in Holding status waiting for a slot |
| Setup → Scheduled Jobs | Schedulable 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;
JobItemsProcessedincrements as chunks complete.
Verified against: Apex Developer Guide — Monitoring Asynchronous Apex. Last reviewed 2026-05-17.