Backfills are the thing your future self will thank you for designing
The day you discover a bug that's been silently corrupting a metric for three weeks, you have two options: fix the code going forward, or fix the code and rerun the corrected pipeline for the past three weeks. The second option is a backfill, and it only works if your pipeline was designed for it.
What makes a pipeline backfillable
- Parameterized by window. The pipeline takes a logical date / window as input — not
NOW(). - Idempotent writes. Rerunning for a window replaces, not appends.
- No hidden state. No "only run for new rows since last run" without an explicit watermark you can override.
- Source data is reachable. The upstream API or warehouse can serve the historical window — check this before the bug, not after.
Time-travel reads
Modern lakehouse formats (Iceberg, Delta Lake) support time-travel reads — "give me this table as it was on 2026-04-01." This is a separate idea from backfilling — backfilling rewrites history, time-travel reads from the past as it was. Together they let you answer "what would yesterday's report have shown if the bug had been fixed two weeks ago?" — a question that's invaluable when explaining changes to stakeholders.