Stackbook Logo
reliability-opsestablished · low operational burden

Idempotent Batch Jobs

Also known as: rerunnable-jobs, safe-retry-batch

Intent

Make batch jobs produce the same result when run multiple times so retries and reruns are safe.

Problem

Batch jobs fail midway, are retried by schedulers, or are rerun by operators. If each run appends or mutates blindly, duplicates and partial writes corrupt the output.

Forces

  • •Failures are normal in distributed jobs
  • •Retries and backfills must be cheap and safe
  • •Output stores may lack transactions
  • •Deterministic inputs are required for deterministic outputs

Solution

Overview

A job is idempotent if running it once or many times with the same inputs leaves the same final state. For batch pipelines this converts failure handling into a single rule: just run it again.

How it works

The two main techniques are partition overwrite and keyed merge, combined with atomic publish.

run(date = D):
  input  = raw.events where event_date = D        # fixed snapshot
  out    = transform(input)                        # pure function
  write out to staging/D/
  atomically replace curated/event_date=D with staging/D

With a table format that supports transactions, use a single statement:

INSERT OVERWRITE TABLE curated.daily_sales PARTITION (sale_date = :d)
SELECT ... FROM raw.sales WHERE sale_date = :d;

For upserts, MERGE on the primary key so replays update instead of insert. A run is identified by its logical date, not the time it started, so a retry at noon for yesterday's data processes yesterday's data. Success markers, such as a manifest file written last, let consumers wait for complete partitions.

Pitfalls

  • Using the current timestamp or latest state in logic. Use the logical run date and as-of snapshots.
  • Appending without dedup keys; retries create duplicates. Add unique business keys.
  • Non-atomic publish: consumers read half a partition. Stage then swap or commit.
  • Late-arriving data in a closed partition is ignored on rerun unless the lookback window is defined.
  • External side effects inside the job run twice. Isolate them behind idempotency keys.

Key takeaways

  • Deterministic input plus overwrite or merge equals safe reruns.
  • Publish atomically and mark completion explicitly.
  • Parameterize by logical date, never by wall clock.
  • Idempotence is the foundation for retries and backfills.

✓ When to Use

  • •Scheduled pipelines with retries
  • •Jobs that may need backfill or rerun
  • •Outputs consumed by downstream jobs that must not see partial data

✗ When Not to Use

  • •Inherently non-repeatable side effects such as sending email (use outbox and dedup instead)
  • •Pure streaming with its own exactly-once mechanism
  • •Inputs are mutable and cannot be snapshotted

Pros

  • +Safe retries and reruns
  • +Simplifies recovery to just rerun
  • +Enables backfills and testing

Cons

  • −Full partition overwrite may rewrite more than needed
  • −Needs atomic publish support
  • −Design constraint on every job

Cost Profile

Infrastructure

Low - mostly design discipline

Operational

Low - fewer manual repairs

Cognitive

Low - concept is simple

Failure Modes

  • Append-only write duplicates rows on retry

  • Readers see partially written output

  • Job reads mutable current state so reruns differ

Real-World Examples

Alternatives

    Related Patterns

      Competency Domains

      reliability opsdata state