Skip to content
PHP2Shell: The PHP Bug
Akshay Thakare

Designing Idempotent, Replayable Pipelines

Batch IDs, immutable attempts, manifests, ledgers and watermarks — the building blocks that make 'just re-run it' safe.

ETL / ELTIntermediate3 min readUpdated 11 Oct 2026

The goal

A pipeline is idempotent if running the same batch twice leaves the target exactly as running it once. Retries, operator re-runs and orchestrator restarts all become safe.

Building blocks

ConceptWhat it isWhat it protects
batch_idOne logical publication (e.g. a business date)Identity for replay checks
attempt_idOne physical try at extracting that batchRetries never overwrite earlier evidence
ManifestExplicit list of files, counts and checksums for an attemptReplays read selected inputs, not a folder scan
LedgerCommitted batches with a content fingerprintSecond publish returns ALREADY_PUBLISHED; different content under the same ID fails
WatermarkCommitted upper bound per sourceOnly moves forward, only on successful commit

The flow

FlowchartSwipe to explore →

Rendering flowchart

One batch, step by step

  1. 1

    Extract into a new attempt

    Write JSONL into raw/batch_id=…/attempt_id=…/. The directory must not exist yet — attempts are never reused.
  2. 2

    Write the manifest last

    List every file with bytes and a checksum. Its presence means the attempt is complete.
  3. 3

    Validate before compute

    Check expected datasets, path prefixes, counts and checksums. A missing or corrupt file stops the batch here.
  4. 4

    Check the ledger

    Same batch, same content → ALREADY_PUBLISHED. Same batch, different content → fail loudly.
  5. 5

    Publish in one transaction

    Facts, history, the ledger row and the new watermark commit together — or not at all.

Rules of thumb

  • Write the manifest last. Its existence means the attempt is complete
  • Never mutate an attempt. Recover with a fresh attempt instead
  • Upserts by natural key for facts; never blind inserts
  • Advance watermarks inside the publish transaction — never before
  • Late, older batches must not rewind the watermark
  • Notifications and audit files live outside the transaction; their failure must not trigger a republish

A useful test suite

Replay the same batch → identical metrics. Delete a raw file → publication blocked. Inject a failure mid-publish → no partial facts, watermark unchanged. Reuse a batch ID with different content → failure.

Finished this note?

Share