A batch class is invoked with Database.executeBatch(new YourBatch(), scopeSize). The method returns the JobId synchronously while the actual batch runs async in the background.
Basic invocation
Id jobId = Database.executeBatch(new InactiveCaseCleanup());
Uses the default chunk size of 200 records per execute.
With a custom chunk size
Id jobId = Database.executeBatch(new InactiveCaseCleanup(), 100);
Valid range: 1 to 2,000.
Passing parameters to your batch
Use the constructor:
public class FilteredCleanup implements Database.Batchable<sObject> {
private String statusFilter;
public FilteredCleanup(String status) {
this.statusFilter = status;
}
public Database.QueryLocator start(Database.BatchableContext ctx) {
return Database.getQueryLocator(
'SELECT Id FROM Case WHERE Status = :statusFilter'
);
}
// ...
}
// Invoke with parameters
Id jobId = Database.executeBatch(new FilteredCleanup('New'), 200);
Where you can invoke from
| Context | Allowed? |
|---|---|
| Anonymous Apex / Developer Console | Yes |
Controller / @AuraEnabled method | Yes |
| Trigger | Yes (use sparingly) |
Another batch’s finish method | Yes (this is “batch chaining”) |
Another batch’s execute method | Yes, but counts against limits |
@future method | Yes |
Queueable execute | Yes |
Schedulable execute | Yes — common pattern for scheduled batches |
Limits to know
| Limit | Value |
|---|---|
| Concurrent active batch jobs (org-wide) | 5 |
| Jobs in Apex Flex Queue (holding) | 100 |
| Batches you can queue from one transaction | 5 |
| Total async Apex jobs per 24 hours | 250,000 or 200 × user licenses |
If you try to start a 6th concurrent batch directly, you’ll get:
System.LimitException: Too many queueable jobs added to the queue: 2— wording varies by context, but the cause is concurrency.
Excess jobs flow into the Apex Flex Queue with status Holding, then start Processing as slots free up.
Capture and use the JobId
Id jobId = Database.executeBatch(new MyBatch(), 200);
// Look it up
AsyncApexJob job = [
SELECT Status, NumberOfErrors, JobItemsProcessed, TotalJobItems
FROM AsyncApexJob WHERE Id = :jobId
];
System.debug('Batch ' + jobId + ' status: ' + job.Status);
You can also surface the JobId to the user as a tracking reference.
Schedule-then-execute pattern
If you want the batch to run on a cron schedule, wrap it in a Schedulable:
public class NightlyCleanup implements Schedulable {
public void execute(SchedulableContext ctx) {
Database.executeBatch(new InactiveCaseCleanup(), 200);
}
}
// Schedule it once
System.schedule('Nightly Cleanup', '0 0 2 * * ?', new NightlyCleanup());
Common interview follow-ups
- Does
Database.executeBatchwait for the batch to finish? — No. It enqueues and returns. The batch runs async. - Can I abort a queued batch? — Yes —
System.abortJob(jobId). - What’s the difference between
executeBatchandenqueueJob? —executeBatchis forDatabase.Batchableclasses;enqueueJobis forQueueable. Different async types.
Verified against: Apex Developer Guide — Using Batch Apex. Last reviewed 2026-05-17.