Skip to main content

SF-0383 · Scenario · Hard

Given a scenario, we have to process a batch apex with 1000 records with 200 records in each transaction and the last transaction failed while doing the DML operation. What will happen to the processed records?

✓ Verified by Vikas Singhal · Last reviewed 5/17/2026 · Updated for Spring '26

If a Batch job processes 1,000 records in chunks of 200 and the fifth (final) execute() fails on its DML, the first four chunks remain committed — they were each their own transaction, and each one ended with a successful commit. Only the failed chunk rolls back. This is fundamental to how Batch Apex works: each execute() is an independent transaction, not a piece of one big transaction.

The timeline

Chunk 1 (records 1–200):    execute() runs → DML succeeds → COMMITTED
Chunk 2 (records 201–400):  execute() runs → DML succeeds → COMMITTED
Chunk 3 (records 401–600):  execute() runs → DML succeeds → COMMITTED
Chunk 4 (records 601–800):  execute() runs → DML succeeds → COMMITTED
Chunk 5 (records 801–1000): execute() runs → DML fails   → ROLLED BACK
finish() runs                                              → COMMITTED (independently)

After the job ends:

  • Records 1–800 carry whatever changes the batch made (persisted).
  • Records 801–1000 are unchanged — that chunk’s transaction rolled back.
  • NumberOfErrors on AsyncApexJob reflects 1 failed chunk.
  • The Apex Jobs UI shows the job as “Completed” (not “Failed”) if at least one execute succeeded.

Why Salesforce designed it this way

Batch is meant for high-volume work where a single bad row shouldn’t waste the work already done. If the entire job rolled back on any failure, processing 50 million records would be all-or-nothing — one timeout or one bad row late in the job would force a complete restart.

The trade-off is that you have to handle partial success deliberately:

  • Log which chunks failed so you can re-process them.
  • Don’t assume the database is in a fully consistent state mid-job.
  • If you need transactional all-or-nothing semantics, you’ve picked the wrong tool — use Queueable in one transaction instead.

Tracking what failed

Use Database.Stateful to accumulate error info across chunks:

public class MyBatch implements Database.Batchable<sObject>, Database.Stateful {
    private List<Id> failedChunkFirstIds = new List<Id>();

    public void execute(Database.BatchableContext ctx, List<sObject> scope) {
        Database.SaveResult[] results = Database.update(scope, false); // partial-success DML
        for (Integer i = 0; i < results.size(); i++) {
            if (!results[i].isSuccess()) failedChunkFirstIds.add(scope[i].Id);
        }
    }

    public void finish(Database.BatchableContext ctx) {
        // Email the failed Ids, write them to a custom log object, queue a retry
    }
}

Pair Database.update(scope, false) with SaveResult inspection to capture errors per record rather than letting the whole chunk fail.

Catching the exception ≠ saving the chunk

Wrapping the DML in try/catch lets you log the failure, but the transaction has already rolled back by the time you catch. The chunk’s DML is gone. The only way to “save” half a chunk is to break it into smaller writes with explicit savepoints, which is rarely worth the complexity.

What finish sees

finish runs in its own transaction regardless of how many chunks succeeded. You can:

  • Query AsyncApexJob via BatchableContext.getJobId() to get final statistics.
  • Send a completion email — including failure counts.
  • Chain a retry batch for the failed records.

Common interview follow-ups

  • Will the whole job stop after a failed chunk? — No. The next chunk continues. Batch processes all chunks unless explicitly aborted.
  • How do I make it all-or-nothing? — You don’t, with Batch. Use Queueable, or accept that Batch is partial-success.
  • What if start fails? — Whole job fails. Nothing has run yet, so there’s nothing to roll back.
  • What if finish fails?finish is its own transaction. Chunks remain committed. The job is logged with an error.

Verified against: Apex Developer Guide — Using Batch Apex, Apex Transaction Control. Last reviewed 2026-05-17.