Incremental processing with a watermark
Full reloads stop scaling once a table grows past millions of rows. Process a bounded window instead: a watermark ends it, a lookback absorbs late files, and an idempotent write (partition overwrite or MERGE) makes every re-run safe — including re-processing a late window.
At a glance
| When | Append-mostly sources; Cost-sensitive pipelines; Deterministic event/updated timestamps |
|---|---|
| Where | Batch Processing |
| Why | Incremental only pays off if it is safe to re-run — the watermark bounds the cost and the idempotent write bounds the blast radius. |
Learning objectives
- Bound incremental work with a watermark and a lookback window
- Write incremental output idempotently so a re-run is safe
- Absorb late-arriving files without re-running history
What you need
- An append-mostly source with deterministic event or updated timestamps
- A table past millions of rows where full reloads cost too much
Steps
- Process a window that ends at a watermark and starts a lookback before it: scan from (max(watermark) - lookback) to now. (from pattern-batch-incremental-watermark )
- The lookback absorbs late arrivals; the watermark bounds the work. (from pattern-batch-incremental-watermark )
- Write idempotently (partition overwrite or MERGE) so a re-run is safe. (from pattern-batch-incremental-watermark )
- Handle deletes explicitly (soft-delete or periodic full refresh) — they don't arrive in an append-only stream. (from pattern-batch-incremental-watermark )
- Watch a naive is_incremental() without a lookback — it silently drops late data. (from pattern-batch-incremental-watermark )
- Files arrive after the daily job already ran, so yesterday's numbers change the next morning. (from runbook-late-files )
- Re-process the late window idempotently (partition overwrite or MERGE), and widen the reprocessing window to cover observed lateness. (from runbook-late-files )
Check yourself
- A re-run for the same window produces identical output — partition overwrite or MERGE, no appends.
- Yesterday's late files are absorbed by the lookback, and no full reload ran.
Worked example
The incremental scan — from pattern-batch-incremental-watermark
Process a window that ends at a watermark and starts a lookback before it.
scan from (max(watermark) - lookback) to now
The lookback absorbs late arrivals; the watermark bounds the work. Write
idempotently (partition overwrite or MERGE) so a re-run is safe.
List raw-file arrival times — from runbook-late-files
aws s3api list-objects-v2 --bucket b --prefix in/ --query 'Contents[].LastModified'
What to monitor — from runbook-late-files
- max file lateness
- count of late arrivals per run
Sourced from
Security scan
Last sweep 2026-10-24: 0 finding(s), 0 marked as examples.
Common gotchas
- A naive is_incremental() without a lookback silently drops late data.
- Re-running the whole partition for one late file is wasteful — overwrite windows, not history.
- Timezone mismatch between partner and pipeline shifts lateness by hours — measure arrival times in UTC.
Production considerations
- Adopt a watermark policy: reprocess the last N days every run.
- Use idempotent writes keyed by business date so a re-run is safe.
Diagram
incremental run
|
|- watermark --> window = [max(watermark) - lookback, now]
|
|- lookback --> late files absorbed, no full reload
|
|- write --> OVERWRITE dt=... / MERGE --> re-run safe
|
|- deletes --> soft-delete or periodic full refresh
Registry stats
| Verification | community · Oct 21, 2026 |
|---|---|
| Completeness | 81 |
| Trust multiplier | ×1.25 |
| Composite | 34.15 · adequate |
| Freshness | 3 days since last source check |
| Difficulty | intermediate |
| Version | 0.1.0 |
| License | CC-BY-4.0 |
| Security flags | none |
Did this solve your problem?
Incremental processing with a watermark