Hightouch
A weekend of work, and real gaps remain.
Reverse ETL: takes a query against your warehouse and keeps the result in step with the tools your teams use — CRM, ad platforms, support.
Build me the reverse ETL I actually need instead of Hightouch. The pattern is simple and the difficulty is entirely in the destinations. **Build it for the two or three destinations you actually use**, and it is a weekend rather than a platform. STACK - Node 20+ with Fastify - SQLite through better-sqlite3, WAL mode, for the sync state - A worker process - Caddy in front THE DATA MODEL - models: id, name, sql, primary_key, source_ref - syncs: id, model_id, destination, mapping_json, mode, schedule, is_active — mode is upsert, update-only, or mirror - rows_state: sync_id, primary_key, row_hash, remote_id, last_synced_at, status — **the whole trick lives here** - runs: id, sync_id, started_at, finished_at, added, changed, removed, failed - failures: id, run_id, primary_key, payload_json, error, at CHANGE DETECTION, THE CORE IDEA - Run the query, hash each row, compare with the stored hash. Send only what changed - **This is what makes reverse ETL affordable**: destinations charge by call and rate-limit hard, and sending everything every hour is what breaks a naive version on day one - A removed primary key means the row left the query result. Decide per sync whether that deletes at the destination or does nothing — and default to doing nothing, because a bad query should not empty your CRM WRITING TO A DESTINATION SAFELY - Batch to the destination's own maximum, respect its rate limit, and back off on 429 with the Retry-After header rather than a guess - **Idempotency on every write**, keyed by the primary key. A retry after a timeout must not create a duplicate contact - Partial batch failures are the norm: record the failing rows individually and continue. One bad email address must not stop the other four thousand - Store the remote id when the destination returns one, so the next run updates instead of searching GUARD RAILS THAT PREVENT DISASTERS - **A change threshold: if a run would modify more than a set share of the rows, stop and ask.** A query edited at five in the afternoon that suddenly matches everybody is the incident this prevents, and it will happen - A dry run showing exactly what would be added, changed and removed - A per-sync daily write cap OBSERVABILITY - Every run recorded with counts; a failure list with the payload and the destination's own error text - Alert on a run failing twice, on a run that syncs zero rows when it normally syncs thousands, and on a rejection rate above a threshold - **Zero rows is the failure nobody alerts on**, and it looks exactly like success in a log WHAT MATTERS MOST Row hashing and the change threshold. The first makes it cheap enough to run; the second stops one wrong query rewriting a whole system.
What you lose
- Connectors to dozens of destination APIs, each with its own quirks
- Change detection and rate handling done for you
- Sync observability when a destination starts rejecting rows
- The maintenance as those APIs change
If you would rather not build
- Grouparoo-style patterns, or a script per destination
- A cron job with a hash column, which is genuinely the whole idea
The escape hatch
open source · no votes, no paid placement
Airbyte
$0Open-source data movement with many connectors; self-hostable.
airbytehq/airbytefree · open source
Why this verdict
our own opinion · changed only by a person
54/100
Verdict kinda at 54: the sync engine is small and the connectors are endless. The change threshold is the guard that separates a tool from an incident.
History
tracked since 14 Aug 2026 · nothing is ever overwritten
Nothing recorded yet. This chart fills in once the page has visitors, votes or prompt copies — it will not draw a flat line to look busy.
Questions about Hightouch
answered from the record above
Is Hightouch free?
No — the plan we track is $350 a month. Starter from around $350/month, priced by destinations and synced records.
Can you replace Hightouch by building your own?
ALMOST. A weekend of work, and real gaps remain. Replacement score 54 out of 100, build time a weekend. Read what you lose before you decide.
How much does Hightouch cost?
$350 a month on Starter — $4,200 a year. Recorded 14 Aug 2026.
What do you lose by replacing Hightouch?
Connectors to dozens of destination APIs, each with its own quirks; Change detection and rate handling done for you; Sync observability when a destination starts rejecting rows; The maintenance as those APIs change. If any of those carry weight for you, keep paying.
Is there an open-source alternative to Hightouch?
Yes: Airbyte, dbt. The prompt on this page is for when you want it your way instead.
Related entries
same category first, most replaced first
Every week, something stops being worth paying for.
New verdicts, prices that moved, entries added. One email a week. Unsubscribe in one click. Nothing is being sent yet — your address is kept here, and the first issue is the first thing it is used for.
free forever · no tracking pixel · stored here, never passed to anyone

