
Batch Apex – When would you need to use it?
You may find yourself in a situation where you need to process a lot of data on an object in your Salesforce instance or even simply data from an API endpoint. Salesforce has governor limits that make processing very large data sets or running complex operations on those data sets tricky. You can only have your process run for so many seconds or take up so much memory.
So, when you need to process a lot of data in Salesforce, use Batch Apex!
When Do You Need To Use Batch Apex?
Before we get into how to use Batch Apex, let’s talk about when you would use it. Batch Apex is commonly used to:
- Process a large set of data, namely Salesforce records
- Communicate with an API and process a large payload
- Complete a long running operation
Batch Apex allows you to do this because the governor limits are expanded a bit and the code is processed in chunks, or batches. As long as no individual batch hits governor limits, the operation will complete.
Now, let’s get started!
Batch Apex Class Structure
To create a Batch Apex class, you need to implement the Database.Batchable interface on your class. This interface requires three methods: start, execute, and finish. Your methods also need to have the proper return type and parameters:
- Start method: This method takes in a Database.BatchableContext Object and returns a list of sObjects or a Database.QueryLocator object. The start method initializes the list of sObjects being processed by the class.
- Execute method: This method takes in the list of sObjects from the start method and a Database.BatchableContext object. This method is where the majority of the processing is done.
- Finish method: This method takes in a Database.BatchableContext object.
To look at some code, the batchable class looks like this:
global class MyBatchClass implements Database.Batchable<sObject>{
global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {}
global void execute(Database.BatchableContext BC, list<sObject>){}
global void finish(Database.BatchableContext BC){}
}
A Practical Example
This looks great, but it’s not helpful if you’re looking to follow a practical example. To show you a more helpful example, let’s make a batch class for the Account object:
global class MyBatchClass implements Database.Batchable<Account>{
global List<Account> start(Database.BatchableContext BC){
}
global void execute(Database.BatchableContext BC, List<Account> scope){
}
global void finish(Database.BatchableContext BC){
}
}
Now, this looks a little more readable. You can see that I am going to return a list of Accounts in my start method, the execute method will take in the same list of Accounts, and the finish method will do some post processing. A few things to notice:
- The Database.BatchableContext BC object is for Salesforce to recognize it as a batchable class. You do not declare it anywhere. It is created when you call the class to run, which will be shown at the end
- The execute method is called with whatever the start methods returns automatically. You do not have to manually write MyBatchClass.execute(List<Account>)
Say we want to process all our Accounts and add ‘123’ to their names. We would use the above class and do the following:
global class MyBatchClass implements Database.Batchable<Account>{
global List<Account> start(Database.BatchableContext BC){
List<Account> appendNames = [SELECT Id, Name FROM Account];
return appendNames;
}
global void execute(Database.BatchableContext BC, List<Account> scope){
for(Account append : scope){
append.Name = append.Name + ' 123';
}
update scope;
}
global void finish(Database.BatchableContext BC){
system.debug('Batch finished!');
}
}
Now that the class has been created, let’s run it! The class can be scheduled or it can be run manually. To run it manually, go to the developer console and create an instance of the class and pass it to the Database.executeBatch method. This method takes in the class, or the class and an integer variable called the scope. The scope specifies how many records to process in each batch.
For example, if my class returns 100 records and I want to process them 5 at a time, I would pass 5 as the scope for the executeBatch method. This will create 1 run of the start method, 20 runs of the execute method, and 1 run of the finish method:


If you count it, there are 22 executions of Batch Apex now, just like we thought there would be:


And there you have it! A practical example of Batch Apex.
Other Considerations For Batch Apex
Batch Apex has a few more nuances to it that I will list out here:
- If you want to retain values of variables across batches, specify Database.Stateful in the class definition. This will allow a variable declared within the class to keep its value during processing. This is useful if you are maintaining a counter or some other value that is affected by all the records.
- A constructor can be created to pass in additional values to the batch class.
To show the second point, take our existing batch class. Say I wanted to specify what string I wanted to add to all the accounts when I execute the class. I would modify my class to be:
global class MyBatchClass implements Database.Batchable<Account>{
global String className;
global MyBatchClass(String namePassedIn){
className = namePassedIn;
}
global List<Account> start(Database.BatchableContext BC){
List<Account> appendNames = [SELECT Id, Name FROM Account];
return appendNames;
}
global void execute(Database.BatchableContext BC, List<Account> scope){
for(Account append : scope){
append.Name = append.Name + ' ' + className;
}
update scope;
}
global void finish(Database.BatchableContext BC){
system.debug('Batch finished!');
}
}
className is the class variable that is being set when the class is executed. It will allow me to specify something to append to the Account names. The constructor, in this case, is simply assigning the parameter passed into it to the class variable:


To learn more about Apex, try your hand at some Trailheads. If you are having issues with Apex, my article on 9 common Apex errors may help!