Table of Contents

  1. Quick Decision Framework
  2. What Is Batch Apex?
  3. What Is Queueable Apex?
  4. Side-by-Side Comparison
  5. Chaining Jobs
  6. Error Handling
  7. Real-World Examples
  8. Governor Limits Reference

One of the most common architectural decisions Salesforce developers face is: should I use Batch Apex or Queueable Apex? Both process work asynchronously, both have their own governor limits, and both are appropriate in different situations. Choosing the wrong one leads to avoidable complexity and maintenance headaches.

Quick Decision Framework

Before diving into the details, here is the fast answer:

Rule of thumb: Processing data at scale = Batch. Offloading targeted async work = Queueable. When in doubt, think about how many records you're processing and whether you need scope control.

What Is Batch Apex?

Batch Apex is designed for processing large volumes of records. It implements the Database.Batchable interface with three methods:

public class UpdateAccountStatusBatch implements Database.Batchable<SObject> {

    public Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator(
            'SELECT Id, AnnualRevenue FROM Account WHERE Rating = null'
        );
    }

    public void execute(Database.BatchableContext bc, List<Account> scope) {
        for (Account acc : scope) {
            acc.Rating = acc.AnnualRevenue > 1000000 ? 'Hot' : 'Warm';
        }
        update scope;
    }

    public void finish(Database.BatchableContext bc) {
        System.debug('Batch complete: ' + bc.getJobId());
    }
}

// Execute:
Database.executeBatch(new UpdateAccountStatusBatch(), 200);

Key characteristics of Batch Apex:

What Is Queueable Apex?

Queueable Apex implements the Queueable interface with a single method: execute(QueueableContext context). It was introduced to overcome the limitations of @future methods — specifically to support callouts, job chaining, and passing complex objects.

public class SendWelcomeEmailJob implements Queueable {
    private List<Id> userIds;

    public SendWelcomeEmailJob(List<Id> userIds) {
        this.userIds = userIds;
    }

    public void execute(QueueableContext context) {
        List<User> users = [SELECT Id, Email, Name FROM User WHERE Id IN :userIds];
        // ... send welcome emails
    }
}

// Enqueue from a trigger:
System.enqueueJob(new SendWelcomeEmailJob(userIds));

Key characteristics of Queueable Apex:

Side-by-Side Comparison

Chaining Jobs

Both mechanisms support chaining, but with important differences.

Batch chaining — chain in the finish() method:

public void finish(Database.BatchableContext bc) {
    Database.executeBatch(new NextBatchJob(), 200);
}

Queueable chaining — enqueue a new job inside execute():

public void execute(QueueableContext context) {
    // ... do work ...
    if (hasMoreWork) {
        System.enqueueJob(new NextQueueableJob(remainingIds));
    }
}
Important: You cannot enqueue a Queueable job from within a Batch Apex execute() method. You CAN do it from finish(). This is a common source of confusion and runtime errors.

Error Handling

Batch Apex has more built-in error isolation — if one batch chunk fails, the other chunks continue processing. The failure is recorded in the AsyncApexJob record. Queueable Apex, by contrast, fails the entire job if an exception is thrown and not caught.

Best practice for Queueable error handling:

public void execute(QueueableContext context) {
    try {
        processWork();
    } catch (Exception e) {
        insert new Error_Log__c(
            Message__c = e.getMessage(),
            Stack_Trace__c = e.getStackTraceString()
        );
    }
}

Real-World Examples

Use Batch Apex for:

Use Queueable Apex for:

Governor Limits Reference

Final recommendation: When your requirement involves processing ALL records of a type, batch is almost always the right choice. When your requirement involves reacting to a specific event with a targeted set of work, queueable is cleaner and more flexible. Understanding the nuance between these two tools is a hallmark of a senior Salesforce developer.