• Articles
  • Tutorials
  • Interview Questions

What is Batch Apex in Salesforce?

Table of content

Show More

Consider a situation wherein you have to process large amounts of data on a daily basis and have to delete some unused data. It would be difficult to manually do so. This is where batching with Apex Salesforce comes to your rescue.

Watch this informative video on Salesforce from Intellipaat:

Video Thumbnail

What is Batch Apex in Salesforce?

Batch Apex in Salesforce is specially designed for a large number of records, i.e., here, data would be divided into small batches of records and then evaluated. In other words, the Batch Class in Salesforce is specifically designed to process bulk data or records together; it has a greater governor limit than the synchronous code.

Advantages of Batch Apex in Salesforce

  • Whenever a transaction is executed, Batch Apex ensures that the code stays within the governor limit.
  • Until a batch is not successfully executed, Batch Apex won’t execute the following batches.
  • A large set of records can be processed together regularly using Batch Apex Classes.
  • The interface can be scheduled to run batches at different periods
  • Asynchronous operations can be implemented by Batch Apex Classes.
  • Batch jobs are invoked programmatically during the runtime; they can be operated on any size of records, with a maximum of 200 records per batch. You can break down a larger record data into 200 records per batch to execute it better.

Get 100% Hike!

Master Most in Demand Skills Now!

Why use Batch Apex in Salesforce rather than normal Apex?

There are various reasons why Batch Apex is better than normal Apex, some of which are mentioned below:

  • SOQL Queries: Normal Apex uses 100 records per cycle to execute SOQL queries, whereas Batch Apex does the same with 200 records per cycle.
  • Retrieval of SOQL Queries: Normal Apex can retrieve 50,000 SOQL queries, but, in Batch Apex, 50,000,000 SOQL queries can be retrieved.
  • Heap Size: Normal Apex has a heap size of 6 MB; whereas, Batch Apex has a heap size of 12 MB.
  • Errors: When executing bulk records, Normal Apex classes are more vulnerable to encountering errors compared to Batch Apex.

Batch Class in Salesforce

When using a Batch Class in Salesforce, the batchable interface needs to be implemented first. It has the following three methods:

  • Start: This method is called at the start of a batch job to collect the data on which the batch job will be operating. It breaks the data or records into batches. In some cases, the ‘QueryLocator’ method is used to operate with a simple SOQL query to generate the scope of the objects inside a batch job.
    • Syntax:
global void execute(Database.BatchableContext BC, list<sobject<) {}
  • Execute: This method executes after the Start method, and it does the actual processing for each batch separately.
    • Syntax:
global void execute(Database.BatchableContext BC, list<sobject<) {}
  • Finish: This method will be called at last. Since this method is called at the end, it is responsible for performing post-processing operations such as sending an email. When this process is called all batches are already executed.
    • Syntax:
global void finish(Database.BatchableContext BC) {}

Implementing the Database.Batchable Interface

The ‘Database.Batchable’ interface needs to implement three methods:

  1. Start Method
public (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {}

At the start of a batch Apex job, call the start method to collect the records or objects to pass to the interface method, and execute. It will return either a Database.QueryLocator object or an iterable that has the objects or records passed to the job.

Use the ‘Database.QueryLocator’ object when using a simple query like SELECT to get the scope of objects in the batch job. If you use a ‘QueryLocator’ object, the governor limit for the total number of records retrieved by SOQL queries is bypassed.

For example, a batch Apex job for the ‘Account’ object can return a QueryLocator for up to 50 million records in an organization. Another instance is the sharing recalculation for the Contact object. It returns a QueryLocator for all account records in an organization.

An iterable can be used to create a complex scope for the batch job as well as a custom process for iterating through the list. If you use it, the governor limit for the total number of retrieved records by SOQL queries still applies.

  1. Execute Method
public void execute(Database.BatchableContext BC, list<P>){}

The execute method is used to do the required processing for each chunk of data; it is called for each batch of records that are passed to it. This method takes the following:

  • A list of sObjects like List<sObject> or a list of parameterized types
  • A reference to the BatchableContext object

If a Database.QueryLocator is implemented, the returned list should be used.

The batches of records are executed in the order in which they are received from the start method. However, the order in which the batches of records execute isn’t guaranteed, as it depends on various factors.

  1. Finish Method
public void finish(Database.BatchableContext BC){}

The finish method is ideal for sending confirmation emails or executing post-processing operations; it is called after all the batches are processed.

Every batch Apex job execution is considered a discrete transaction. For example, a batch Apex job with a thousand records executed with no optional scope parameter from Database.executeBatch is considered as five transactions that have 200 records each.

Apex governor limits are reset for every transaction. In case the first transaction succeeds but the second one fails, the database updates from the first transaction aren’t rolled back.

Using Database.BatchableContext

A reference to a ‘Database.BatchableContext’ object is needed by all methods in the Database.Batchable interface. This object can be used to track the progress of the batch job. Following is the instance method for the Database.BatchableContext object:

Database.BatchableContext

Using Database.QueryLocator to Define Scope

The start method can return either a ‘Database.QueryLocator’ object containing the records that are to be used in the batch job or an iterable. The following is an example of using Database.QueryLocator:

Using Database.QueryLocator

Using an Iterable in Batch Apex to Define Scope

As mentioned above, the start method returns either a ‘Database.QueryLocator’ object containing the records that are to be used in the batch job or an iterable. Using an iterable makes it possible to step through the returned items more easily. The following is an example of how to use an iterable in Batch Apex:

Using Iterable in Batch Apex

Creating an Apex Batch Class in Salesforce with an Example

Batch Apex splits the records into batches and processes them asynchronously, which allows the records to be processed in multiple threads. Without exceeding the processing limit, Batch Apex can run through millions of records. Also, if one batch fails to process successfully, the successful transactions will not be rolled back.

Before writing the Batch Apex Class, you have to implement the database batchable interface. If you don’t know what an interface is, it’s similar to a class where none of its functions are implemented. However, the signature of each function is there with an empty body. This interface has three main methods, which must be implemented: start(), execute(), and finish().

Now, let’s go through the steps given below and create a Batch Class in Salesforce:

Step 1: Search for Apex Salesforce Classes in Setup.

Search for Apex Salesforce Classes in Setup

Step 2:  Once you open Salesforce Apex Classes, click on New to create a new Apex Class.

Salesforce Apex Classes

Step 3: Below is the screen on which you’ll have to write your code.

screen

The following is the program that updates the account name in the account object with the keyword ‘Updated’ after the account name.

Screen Apex Classes

// Batch Job for Processing the Records

  global class batchAccountUpdate implements Database.Batchable {

// Start Method

    global Database.QueryLocator start(Database.BatchableContext BC) {

        String query = 'SELECT Id,Name FROM Account';

        return Database.getQueryLocator(query);
    }

   // Execute method

    global void execute(Database.BatchableContext BC, List scope) {

         for(Account a : scope)

         {a.Name = a.Name + 'Updated';            
         }

         update scope;
    }   

    // Finish Method

    global void finish(Database.BatchableContext BC) {
    }

}

How to Execute Batch Class in Salesforce?

Executing a Batch Class in Salesforces only takes a few clicks on the developer console. So, follow the steps given below to execute the Batch Class that you created earlier. We’ve considered the above Batch Class as an example. If you want to execute another file, you can change the name accordingly.

Step 4: After writing the code, you’ll have to go to the developer console, click on Debug, and then click on Open Execute Anonymous Window. You’ll see the following screen:

enter apex code

The basic syntax of the execution code will be: 
Id &amp;lt;variable_name&amp;gt; = new &amp;lt;variable_name&amp;gt;;
database.ExecuteBatch(new &amp;lt;class_name&amp;gt;(), batch_size);

Now, enter the following code in the box and click on Execute:

batchAccountUpdate b = new batchAccountUpdate();
database.executeBatch(b);

step 5

Step 5: The following will be the output after you click on Execute:

click on ExecuteAs you can see, the status Success means that the account details have been updated.

Using the Database.executeBatch Method to Submit Batch Jobs

The Database.executeBatch method can be used to programmatically begin a batch job.

A thing to keep in mind is that when Database.executeBatch is called, Salesforce adds the process to the queue. Based on the availability of the service, the actual execution can be delayed.

The Database.executeBatch method considers the following two parameters:

  • An instance of a class implementing the Database.Batchable interface.
  • An optional parameter scope that specifies the number of records to pass into the execute method.

The optional parameter should be used when there are multiple operations for each record that are being passed in and run into governor limits. Limiting the number of records will limit the number of operations per transaction. This value must be greater than zero.

The maximum value of the optional scope parameter of Database.executeBatch can be 2,000 if the start method of the Batch Class returns a QueryLocator. If the value is set higher than that, Salesforce breaks the records into smaller batches of up to 2,000 records.

If an iterable is returned by the start method of the Batch Class, the scope parameter value will have no upper limit. However, in case of high numbers, you could run into other limits. The optimal scope sizes are all in factors of 2000, for example, 100, 200, 400, and so on.

The Database.executeBatch method returns the ‘AsyncApexJob’ object ID, which can be used to track the progress of the job. For example:

Database.executeBatch Method

This ID can also be used with the System.abortJob method.

Holding Batch Jobs in the Apex Flex Queue

Using the Apex Flex Queue, up to a hundred batch jobs can be submitted. The outcome of Database.executeBatch is as follows:

  • The batch job is placed in the Apex Flex Queue, and its status is set to Holding.
  • If the Apex Flex Queue has the maximum number of jobs i.e., 100 jobs, Database.executeBatch throws a LimitException and doesn’t add the job to the queue.

On a side note, if the Apex Flex Queue is not enabled, the batch job is added by Database.executeBatch to the batch job queue with the status ‘Queued.’ If the concurrent limit of active or queued batch jobs has been reached, a LimitException is thrown, and the job isn’t queued. 

Batch Job Statuses

The table below lists all the possible statuses for a batch job:

Batch Job Statuses

Batch Class Schedule in Salesforce

You can schedule your Batch Apex Class using the developer console or scheduler. These Batch Classes can then be executed at a particular time. However, you have to write the Apex Class File in order to execute the batchable interface. You can also chain two or more Apex Batch Classes together to execute one job after another. Moreover, you can split an Apex record into batches and schedule groups of them to be executed at a particular time.

Mentioned below is an example of a Schedulable Apex class interface:

Global class apexScheduler implements Schedulable
{
Global void execute(SchedulableContext sc)
{
batchAccountUnpdate b=new batchAccountUpdate();
}
}

Save the above Apex class on your device. Now, go to the Setup>> Apex Classes>> ScheduleApex, browse the SchedulerApex class, and set the execution time.

Using the System.scheduleBatch Method

The System.scheduleBatch method can be used to schedule a batch job to run once at a future time. It takes the following parameters:

  • An instance of a class using the Database.Batchable interface
  • The name of the job
  • The time interval (in minutes) after which the job will start executing
  • An optional scope value that specifies the number of records to pass into the execute method.

The optional scope value is to be used when there are several operations for each record that are being passed in and run into governor limits. Limiting the number of records will limit the operations per transaction, and this value must be greater than zero.

If a QueryLocator is returned by the start method of the batch class, the optional scope parameter of Database.executeBatch can have 2,000 as the maximum value. If the value is set higher, Salesforce breaks the records into smaller batches of up to 2,000 records.

If an iterable is returned by the start method of the batch class, the scope parameter value will have no upper limit. However, in case of a high number, there might be other limits. The optimal scope size is a factor of 2000.

 The System.scheduleBatch method returns the scheduled job ID (CronTrigger ID).

Using Callouts in Batch Apex

To use a callout in Batch Apex, Database.AllowsCallouts have to be specified in the class definition. Callouts include HTTP requests and methods defined with the web service keyword. The following is an example of how to use a callout in Batch Apex:

public class SearchAndReplace implements Database.Batchable&amp;lt;sObject&amp;gt;, Database.AllowsCallouts{
}

Batch Apex Limitations

The following are the governor limits and the other limitations of Batch Apex:

    • Only five batch jobs can be queued or be active concurrently.
    • A maximum of 100 holding batch jobs can be held in the Apex Flex Queue.
    • A maximum of five batch jobs can be submitted in case of a running test.
    • There can be up to 250,000 Batch Apex method executions per day or the number of user licenses in an organization multiplied by 200 — whichever is greater. This limit is for the entire organization; it is shared with all asynchronous Apex methods: Batch Apex, Queueable Apex, Scheduled Apex, and future methods.
    • The Batch Apex start method can have a maximum of 15 query cursors open at a time per user while the execute method and finish method, each have a limit of five per user.
    • Only 50 million records can be returned to the ‘QueryLocator’ object. If more than that is returned, the batch job is immediately terminated and marked as ‘failed.’
    • If the start method of the batch class returns a QueryLocator, the optional scope parameter value of executeBatch can be up to 2,000. If set to a higher value, Salesforce breaks the records into smaller batches of up to 2,000 records.

If the start method of the batch class returns an iterable, the scope parameter value has no upper limit. If you use a high number, you can, however, run into other limits. The optimal scope size is a factor of 2000.

    • If the optional scope parameter of executeBatch has no size specified, Salesforce breaks up the records returned by the start method into batches of 200. Each batch is then passed to the execute method by the system. The governor limits of Apex are reset for each execution.
    • The start, execute, and finish methods can use up to 100 callouts each.
    • Only one start method of a batch Apex job can run at a time in an organization. Batch jobs that haven’t started yet remain in the queue in the meantime. This limit doesn’t cause any batch job to fail and execution methods run in parallel if multiple jobs are running.
    • Using FOR UPDATE in SOQL queries to lock records during updates is not applicable to Batch Apex.

Best Practices in Batch Apex Salesforce

  • One should be extremely careful when planning to invoke a batch job from a trigger. The number of batch jobs added by the trigger should not be more than the limit. In particular, API bulk updates, mass record changes through the user interface, import wizards, and all cases that allow more than one record update at a time should be considered.
  • It is important to understand that when Database.executeBatch is called, Salesforce only places the job in the queue. The actual execution can be delayed depending on the service’s availability.
  • When testing Batch Apex, only one execution of the execute method should be tested. To limit the number of records passed into the execute method, use the scope parameter of the executeBatch method and ensure that no governor limits are reached.
  • The executeBatch method starts an asynchronous process. When Batch Apex is tested, it must be ensured that the asynchronously processed batch job is completed before testing against the results. startTest and stopTest test methods should be used around the executeBatch method to ensure its completion before continuing with the test.
  • Stateful should be used with the class definition if instance member variables or data across job transactions need to be shared. Otherwise, at the start of each transaction, all member variables are reset to their initial state.
  • Methods that are declared as future aren’t allowed in classes that use the Database.Batchable interface.
  • Methods can’t be called from a Batch Apex Class if they are declared as future.
  • When a Batch Apex job is run, the user who submitted the batch job receives email notifications. If a managed package includes the code and the subscribing organization is running the batch job, the recipient listed in the Apex Exception Notification Recipient field receives the notifications.
  • Standard governor limits for anonymous block, Visualforce controller, or WSDL method are used by each method execution.
  • An AsyncApexJob record is created by each Batch Apex invocation. Use the AsyncApexJob record’s ID to construct a SOQL query and retrieve the job’s status, number of errors, progress, and submitter.
  • For every 10,000 AsyncApexJob records, Apex creates an AsyncApexJob record of type ‘BatchApexWorker’ for internal use. When querying for all AsyncApexJob records, records of type ‘BatchApexWorker’ should be filtered out using the ‘JobType’ field. Otherwise, the query will return one more record for every 10,000 AsyncApexJob records.
  • All Database.Batchable interface methods that are used must be defined as global or public.
  • The execute method should delete and then re-create all Apex-managed sharing for the records in the batch for the purpose of sharing recalculation. This ensures accuracy and completion.
  • The batch jobs that are queued before a Salesforce service maintenance downtime remains in the queue. After the service downtime ends, and when system resources are available, execution of the queued batch jobs starts. If a batch job was already running when downtime occurred, the batch execution is rolled back and restarted after the service is back up.
  • If possible, reduce the number of batches as much as possible. Salesforce implements a queue-based framework for handling asynchronous processes from such sources as future methods and Batch Apex. This queue balances the request workload.
  • The batch jobs should execute as fast as possible. To achieve this, minimize the Web service callout times and tune queries used in your Batch Apex code. The longer the batch job executes, the more likely it is for the other queued jobs to be delayed when multiple jobs are queued.
  • If Batch Apex is used with Database.QueryLocator for accessing external objects via an OData adapter for Salesforce Connect:
    • Enable Request Row Counts on the external data source; the total row count of the result set must be in each response from the external system.
    • Enable Server-Driven Pagination on the external data source and have the external system determine the batch boundaries and page sizes for large result sets. Typically, server-driven paging is able to adjust batch boundaries to accommodate changing data sets more effectively unlike client-driven paging.

The OData adapter controls the paging behavior (client-driven) when Server-Driven Pagination is disabled on the external data source. If external object records are added to the external system while a job is running, other records can be processed twice. If external object records are deleted from the external system while a job runs, other records can be skipped.

  • When Server Driven Pagination is enabled on the external data source, the batch size at runtime is the smaller of the following:
    • The batch size is specified in the scope parameter of executeBatch. By default, it has 200 records.
    • Page size returned by the external system. It is ideal to set up the external system to return page sizes of 200 or fewer records.
  • Batch Apex jobs run faster when a QueryLocator object is returned by the start method and it doesn’t have related records via a subquery. Avoiding relationship subqueries in a QueryLocator using a faster, chunked implementation allows batch jobs to run. If the start method returns an iterable or a QueryLocator object with a relationship subquery, the batch job implements a slower, non-chunking, implementation.
  • Records can be re-queried inside the execute() method using FOR UPDATE if necessary. It is possible to implement record locking as part of the batch job, ensuring that no conflicting updates are overwritten by DML in the batch job. By simply selecting the ID field in the batch job’s main query locator, one can re-query records.

I hope you had fun learning Batch Apex! In this section, you learned about Salesforce Apex Classes and Batch Apex in Salesforce and you implemented them as well. In the next section of this Salesforce tutorial, you will be learning about Workflow Rules in Salesforce.

Course Schedule

Name Date Details
Salesforce Certification 14 Dec 2024(Sat-Sun) Weekend Batch View Details
21 Dec 2024(Sat-Sun) Weekend Batch
28 Dec 2024(Sat-Sun) Weekend Batch

About the Author

Salesforce Certified Professional

Rahul is a seasoned Salesforce Certified administrator and app builder with 10+ years of experience in many Salesforce technologies, such as Salesforce CRM and business process automation. In his free time, he likes to write and read about the latest technologies.