← Blog Blog · Connectors

Append, upsert, or delete: write modes and what they cost

Loading data isn't one operation. Appending is cheap and streams flat out; upserting makes the destination reconcile every row. faucet-stream gives you both — and is clear about the tradeoff.

faucet-stream·August 25, 2026·~5 min read

Three modes, one config field

A sink's write_mode says how rows land in the destination:

  • append (default) — add rows. No reconciliation, no key lookup — the fastest path.
  • upsert — insert-or-update by key, so re-running a load is idempotent.
  • delete — apply deletes (via a marker), for full CDC mirroring.

Upsert and delete need a key: they require auto-mapped columns and a declared key set, so the destination knows what "the same row" means.

Append has a fast lane

Within append, the Postgres sink offers two write methods: multi-row insert (default) and copy. COPY … FROM STDIN is a streaming bulk load and is meaningfully faster than multi-row INSERT for bulk append — in our Postgres → Postgres benchmark the COPY path led the field.

But COPY has no ON CONFLICT, so it's append-only. Combining write_method: copy with write_mode: upsert is rejected at config time — faucet won't let you ask for a fast path that can't honor the semantics you also asked for.

The cost is where the work is

Append streams: faucet hands the destination bytes and it writes them. Upsert/merge is different — the destination now has to match keys, update existing rows, and maintain indexes for every batch. On a warehouse a MERGE can be several times slower than an append, and that cost lives in the warehouse, not in faucet. Worth knowing when you read a benchmark: an append number is the ceiling; a real upsert pipeline sits below it, bounded by the target's reconciliation cost.

Takeaway

Use append (with COPY where available) when you're loading fresh data — it's the fast lane. Reach for upsert/delete when you need idempotent re-runs or a true mirror, and budget for the destination doing more work. faucet gives you the choice and refuses the incoherent combinations.

Was this useful?

React with 👍, ❤️ or 🚀 to vote, or leave a comment. You sign in with GitHub inside the box below; this site never sees your account.

More on the blog, or read the documentation.

Get started

Your first pipeline runs in five minutes.

Install the CLI, scaffold a config, and move real data — nothing external to stand up.

curl -LsSf https://github.com/faucet-hq/faucet-stream/releases/latest/download/faucet-cli-installer.sh | sh
brew install faucet-hq/faucet-stream/faucet-cli