How the upsert works in Amazon Redshift
Redshift gained a native MERGE in 2023, but the pattern AWS documents for loads, and the one the generator emits, is still delete-and-insert from a staging table inside one transaction: delete every target row whose key appears in staging, then insert the deduped staging rows. It is simple, restartable, and fast when staging shares the target's DISTKEY so the delete join runs on-node.
Load staging with COPY from S3 in multiple files so every slice works in parallel. A SORTKEY on the load timestamp keeps recent rows together, and the DISTKEY on the join id keeps merges local. Deleted rows are only marked until VACUUM reclaims them, so a table merged hourly needs VACUUM DELETE ONLY and ANALYZE on a schedule or query plans drift.
Before you run it
- This is the merge pattern AWS documents for Redshift: replace matched rows wholesale inside one transaction. Give the staging table the same DISTKEY as the target so the DELETE join stays on-node.
- Redshift's native MERGE (2023) works too, but it requires both a WHEN MATCHED and a WHEN NOT MATCHED branch and a source with exactly one row per key; the delete-and-insert form is easier to reason about at scale.
- Deletes leave ghost rows until VACUUM runs; on a busy table schedule VACUUM DELETE ONLY and ANALYZE after the batch.