What is Batch Apex Salesforce?
Batch Apex in Salesforce is used to process a large number of records asynchronously by splitting the work into smaller transactions. It is suitable for jobs such as updating thousands of records, recalculating fields, cleaning data, or processing records on a schedule.
For example, if you need to update a field on every Account record in a Salesforce org, doing it in one normal transaction can hit governor limits. Batch Apex reduces this problem by selecting the records once, dividing them into smaller scopes, and running each scope separately.
The core Batch Apex class implements Database.Batchable and contains three methods: start, execute, and finish. Salesforce documents this pattern in the Apex Developer Guide for Batch Apex and the Database.Batchable interface reference.

How Batch Apex in Salesforce works
Batch Apex Salesforce works in three phases. The start method selects or prepares the records. Salesforce then breaks those records into scopes. The execute method runs once for each scope, and the finish method runs once after all scopes are complete.
- The default scope size is 200 records when you do not pass a scope size to
Database.executeBatch. - You can pass a scope size up to 2,000 records.
- With
Database.QueryLocator, Batch Apex can retrieve up to 50 million records. - Each
executecall is a separate transaction, so governor limits reset for each scope. - Do not depend on a specific processing order unless your code explicitly controls it.
When to use Batch Apex instead of normal Apex
Use Batch Apex when the job is data-heavy and does not need to finish immediately in the current user request. For smaller operations, a trigger, Queueable Apex, Scheduled Apex, or a normal Apex method may be simpler.
| Requirement | Better choice | Reason |
|---|---|---|
| Update a few records immediately | Normal Apex or trigger | Simple transaction is enough. |
| Run one async job with moderate logic | Queueable Apex | Easier to chain and pass complex data. |
| Process thousands or millions of records | Batch Apex | Records are processed in separate scopes. |
| Run large processing on a fixed schedule | Scheduled Apex + Batch Apex | Scheduler starts the batch at the required time. |
Database.Batchable interface methods in Salesforce
To use Batch Apex, write an Apex class that implements Database.Batchable. If you are new to queries, first review how to write an Apex class with the SOQL fields your batch needs.
- Start method.
- execute method.
- Finish method.
Start method in Batch Apex Salesforce
Start method : The start method is automatically called at the beginning of the Batch Apex job. This method collects the records or objects on which the operation should be performed.
- The records are broken down into sub tasks and given to execute method.
Start method syntax :
global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext ***bc***) {}
- The return type of the start method can be Database.QueryLocator or Iterable <Sobject>.
Database.QueryLocator: Use Database.QueryLocator as return type to the start method when you are fetching the records using a simple select Query.
- A normal SOQL query is limited by normal Apex governor limits in a single transaction.
- In Batch Apex,
Database.QueryLocatorcan return up to 50 million records.
But, in the Batch Apex the governor limits for SOQL query are bypassed and we can fetch upto 50 million record using Database.QueryLocator.
Example : –
global Database.QueryLocator Start(Database.BatchableContext bc) {
return Database.getQueryLocator('Select id, name FROM Account');
}
A corrected Apex style version is shown below. Use a concrete return type and keep the method name as start for readability.
global Database.QueryLocator start(Database.BatchableContext bc) {
return Database.getQueryLocator([
SELECT Id, Name
FROM Account
]);
}
Iterable : Use Iterable as a return type when you want to use complex logic or scope to fetch the records for the batch job.
Example :
global class MyTest implements Iterable <Account> {
}
global Iterable<Account> start(Database.BatchableContext bc) {
return new Mytext();
}
Execute method in Batch Apex Salesforce
Execute Method : The records fetched from the start method are divided into batches of records. Each batch scope is passed to the execute method, where the required update, calculation, or processing logic is written.
Execute Method Syntax:
global void execute(Database.ExecutableContext Bc, List<p>) {}
- This method takes two parameters.
- A reference to the Database.BatchableContext object.
- A list of Sobjects such as List<Sobject>, or a list of parameterized types.
The working signature uses Database.BatchableContext. The second parameter is the scope list for that transaction.
global void execute(Database.BatchableContext bc, List<SObject> scope) {
// Process this scope here.
}
Finish method in Batch Apex Salesforce
Finish Method :- When the start method has fetched 1000 records on which we want to perform the operation they are divided into 5 batch/Groups. Each batch/Group of size 200 records.
- On every batch/Group the execute method is called (totally called 5 times).
- After executing every Group/batch the governing limits are reset for the execute method.
- Once all the batches are executed then finish method will be called to send Email notification for post execution work.
Finish Method syntax:
global void finish(Database.BatchableContext BC) {}
Use finish for final logging, a completion email, a summary record update, or a controlled follow-up job. Avoid putting record-by-record processing in finish.
Complete Batch Apex class example for Account updates
This example updates Account records whose Description field is blank. It keeps SOQL in start, bulk processing in execute, and final status logging in finish.
global with sharing class AccountDescriptionBatch implements Database.Batchable<SObject> {
global Database.QueryLocator start(Database.BatchableContext bc) {
return Database.getQueryLocator([
SELECT Id, Description
FROM Account
WHERE Description = null
]);
}
global void execute(Database.BatchableContext bc, List<SObject> scope) {
List<Account> accountsToUpdate = new List<Account>();
for (SObject record : scope) {
Account acc = (Account) record;
acc.Description = 'Updated by Batch Apex';
accountsToUpdate.add(acc);
}
if (!accountsToUpdate.isEmpty()) {
update accountsToUpdate;
}
}
global void finish(Database.BatchableContext bc) {
System.debug('AccountDescriptionBatch completed. Job Id: ' + bc.getJobId());
}
}
How to execute Batch Apex class in Salesforce
Run a Batch Apex class with Database.executeBatch. The second argument is the scope size. The call below starts the Account batch with 200 records per scope.
Id jobId = Database.executeBatch(new AccountDescriptionBatch(), 200);
System.debug('Batch Job Id: ' + jobId);
You can run this from the Developer Console Anonymous Window, from an Apex method, from a scheduled class, or from a controlled admin action. Do not start batch jobs from code that can run repeatedly without a clear guard condition.
Execute Batch Apex from an Apex controller or service class
public with sharing class AccountBatchLauncher {
public static Id runAccountDescriptionBatch() {
return Database.executeBatch(new AccountDescriptionBatch(), 200);
}
}
Monitor Batch Apex job status in Salesforce
Admins can monitor the job from Setup > Apex Jobs. Developers can query AsyncApexJob to check status, processed job items, total job items, and errors.
SELECT Id, Status, JobItemsProcessed, TotalJobItems, NumberOfErrors
FROM AsyncApexJob
WHERE JobType = 'BatchApex'
ORDER BY CreatedDate DESC
Batch Apex best practices for Salesforce data processing
- Filter records in the
startquery so the batch processes only records that need work. - Select only the fields used by the batch logic.
- Avoid SOQL and DML inside loops in the
executemethod. - Use a smaller scope size when each record needs heavy logic, callouts, or large related data.
- Use
Database.update(records, false)if one failed record should not stop the whole scope. - Add
Database.AllowsCalloutswhen the batch must make HTTP callouts. - Add
Database.Statefulonly when values must be preserved across scopes.
Test class pattern for Batch Apex execution
A test class should create its own records, call the batch inside Test.startTest() and Test.stopTest(), and then verify the updated data.
@IsTest
private class AccountDescriptionBatchTest {
@IsTest
static void updatesBlankAccountDescriptions() {
List<Account> accounts = new List<Account>();
for (Integer i = 0; i < 10; i++) {
accounts.add(new Account(Name = 'Batch Test Account ' + i));
}
insert accounts;
Test.startTest();
Database.executeBatch(new AccountDescriptionBatch(), 200);
Test.stopTest();
List<Account> updatedAccounts = [
SELECT Description
FROM Account
WHERE Id IN :accounts
];
for (Account acc : updatedAccounts) {
System.assertEquals('Updated by Batch Apex', acc.Description);
}
}
}
Batch Apex editorial QA checklist
- Does the tutorial explain that Batch Apex is asynchronous and scope-based?
- Does the code include
start,execute, andfinish? - Does the page answer how to execute a Batch Apex class with
Database.executeBatch? - Are the scope and record limits stated carefully: 200 default scope, up to 2,000 scope size, and up to 50 million records with
Database.QueryLocator? - Does the example avoid SOQL and DML inside loops?
Batch Apex Salesforce FAQs
What is Batch Apex in Salesforce?
Batch Apex is asynchronous Apex used to process large record sets in smaller scopes. A Batch Apex class implements Database.Batchable and has start, execute, and finish methods.
How do I execute a Batch Apex class?
Use Database.executeBatch(new ClassName(), scopeSize). For example, Database.executeBatch(new AccountDescriptionBatch(), 200) starts the batch with a scope size of 200 records.
What is the default batch size in Batch Apex?
The default batch size is 200 records when no scope size is passed. A custom scope size can be supplied, up to 2,000 records.
When should I use Database.QueryLocator in Batch Apex?
Use Database.QueryLocator when the batch records can be selected with a SOQL query. It is commonly used for large Salesforce record sets because it can return up to 50 million records for a batch job.
Can Batch Apex make callouts?
Yes. A Batch Apex class can make callouts when it implements Database.AllowsCallouts. Callout limits still apply inside each execute transaction.
TutorialKart.com