Skip to content
Back to skills

Writing Idempotent Transformations

ASecurity

Write data transformations and loads that produce the same result no matter how many times they run — using MERGE/upsert, deterministic partition overwrites, deduplication, and stable keys. Use when a retry could duplicate data, a job is not safe to re-run, a pipeline needs exactly-once effects, or loads must be backfill-safe.

  • 15 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 1, 2026
ai-agentssql

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 1, 2026

npx -y skills add Unknown-333/awesome-data-engineering-skills --skill writing-idempotent-transformations --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Writing Idempotent Transformations?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Writing Idempotent Transformations
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/unknown-333-writing-idempotent-transformations/badge)](https://www.skillsdirectory.com/skills/unknown-333-writing-idempotent-transformations)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: writing-idempotent-transformations
description: Write data transformations and loads that produce the same result no matter how many times they run — using MERGE/upsert, deterministic partition overwrites, deduplication, and stable keys. Use when a retry could duplicate data, a job is not safe to re-run, a pipeline needs exactly-once effects, or loads must be backfill-safe.
---

# Writing Idempotent Transformations

## When to use

- A task may be retried (orchestrator retries, manual re-runs, replays).
- A backfill must not change already-correct numbers or create duplicates.
- You are writing an incremental load, upsert, or partition refresh.
- Do NOT use for one-off exploratory queries with no persisted side effects.

## Why it matters

Failures are normal. Retries, backfills, and replays run the same logic again.
If a job is idempotent, running it once or five times yields the same final
state — so recovery is safe and boring. If not, retries duplicate rows and
backfills silently change history. This is the single most reported source of
data incidents.

## Workflow

```
- [ ] Define the unit of work and its natural key
- [ ] Make writes overwrite-by-key or overwrite-by-partition (never blind append)
- [ ] Remove dependence on wall-clock time / autoincrement / random order
- [ ] Verify: running twice == running once (row counts and checksums match)
```

1. **Pick a deterministic key** for each output row (business key, or a hash of
   the identifying columns).
2. **Replace `INSERT`-append with `MERGE`/upsert** keyed on that key, or with a
   full **partition overwrite** for the window being processed.
3. **Remove non-determinism**: don't key on `now()`, sequence values, or
   unordered `row_number()`; derive timestamps from the data/event, not the run.
4. **Test it**: run the transform twice on the same input and assert identical
   output (count + checksum).

## Patterns

**Delete-insert by partition** — the simplest idempotent load for a time window:
delete the target partition, then insert its freshly computed rows in one
transaction. Re-running reprocesses only that window and cannot duplicate.

```sql
BEGIN;
DELETE FROM fct_orders WHERE order_date = DATE '2026-01-15';
INSERT INTO fct_orders
SELECT ... FROM staging WHERE order_date = DATE '2026-01-15';
COMMIT;
```

**MERGE/upsert by key** — when rows update in place:

```sql
MERGE INTO fct_orders t
USING staging s ON t.order_id = s.order_id
WHEN MATCHED THEN UPDATE SET amount = s.amount, status = s.status
WHEN NOT MATCHED THEN INSERT (order_id, amount, status)
VALUES (s.order_id, s.amount, s.status);
```

**Deduplicate deterministically** — keep the latest version per key with a stable
tiebreaker, so the result never depends on scan order:

```sql
SELECT * FROM (
  SELECT *, ROW_NUMBER() OVER (
    PARTITION BY order_id ORDER BY updated_at DESC, source_file DESC
  ) AS rn
  FROM staging
) WHERE rn = 1;
```

**dbt incremental** — use a `unique_key` and `merge` strategy so re-runs upsert
rather than append; use `insert_overwrite` on partitioned warehouses.

## Common pitfalls

- **Blind `INSERT ... SELECT`** in a retried task — the classic duplicate source.
- **Keying on `current_timestamp`/`uuid()`** — makes every run produce new rows.
- **`ROW_NUMBER()` without a tiebreaker** — nondeterministic when timestamps tie.
- **Appending to a partition instead of overwriting it** — backfills accumulate.
- **Non-transactional delete+insert** — a mid-run failure leaves the target empty;
  wrap both in one transaction or use atomic overwrite.

## References

- [Backfill-safe checklist and anti-patterns](references/CHECKLIST.md)

Files in this skill

  • SKILL.md3.6 KB
  • references/CHECKLIST.md1.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…