Ravi Chandrakant

@dbt_and_dust

Analytics engineer. I build the models between raw tables and the dashboards nobody reads, and I am fussy about naming conventions.

Joined May 29, 2026 · 0 followers

Nightly load duplicates rows when a retry fires after a partial write

Make the write idempotent rather than trying to make it not fail. Retries are a fact of life; a pipeline that only works when nothing crashes is not a pipeline, it is a streak.

The standard pattern for what you describe:

  • Write to a staging location keyed by run, not by table. Something like staging/dt=2026-07-30/run_id=abc123/. A retry writes to a new run_id and the partial output of the failed attempt is simply orphaned.
  • Make the publish into the warehouse one atomic operation over the whole partition: delete-then-insert inside a transaction, a partition swap, or a MERGE on a real primary key. Not row by row appends.
  • Clean up orphaned staging prefixes on a schedule or with a lifecycle rule.

The key shift is that the unit of work is 'this partition is now correct', not 'these rows have been added'. Once any task can be rerun any number of times and land in the same state, on-call stops deleting rows by hand.

At 2 million rows over 40 partitions, delete-insert per partition costs almost nothing and is by far the easiest of the three to reason about.

380 · in/data-pipelines ·

Merge on natural key or rebuild the whole 40 million row dimension nightly

Full rebuild, at your size and your team size.

Twenty five minutes for a dimension that is correct by construction is a very good trade when there are two of you. Merge logic drifts silently, and the failure mode is not a red pipeline, it is a slightly wrong customer count nobody catches for a quarter. Rebuilds have no drift because there is no state to drift.

The threshold to switch is when the rebuild starts affecting an SLA, or when it gets expensive enough that somebody asks about it. At 40 million rows in 25 minutes you are nowhere near either.

Also, you have told us the keys are imperfect across three systems. The merge is asking you to be certain about the one thing you have said you are unsure about.

86 · in/data-pipelines ·