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.

What is batch apex salesforce

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 execute call 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.

RequirementBetter choiceReason
Update a few records immediatelyNormal Apex or triggerSimple transaction is enough.
Run one async job with moderate logicQueueable ApexEasier to chain and pass complex data.
Process thousands or millions of recordsBatch ApexRecords are processed in separate scopes.
Run large processing on a fixed scheduleScheduled Apex + Batch ApexScheduler 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.

  1. Start method.
  2. execute method.
  3. 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 :

</>
Copy
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.QueryLocator can 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 : –

</>
Copy
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.

</>
Copy
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 :

</>
Copy
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:

</>
Copy
 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.

</>
Copy
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:

</>
Copy
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.

</>
Copy
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.

</>
Copy
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

</>
Copy
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.

</>
Copy
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 start query 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 execute method.
  • 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.AllowsCallouts when the batch must make HTTP callouts.
  • Add Database.Stateful only 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.

</>
Copy
@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, and finish?
  • 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.