Data Engineering glossary
What is Reverse ETL?
Reverse ETL copies modelled data from the warehouse or lakehouse back into operational tools such as a CRM, marketing platform or support desk, so the people who use those tools can act on it. Typical examples are lead scores, churn-risk flags and customer audiences computed in the warehouse.
How it works
Classic pipelines move data from operational systems into analytics. Reverse ETL goes the other way: it takes results that only exist in the warehouse and writes them into the systems where sales, support and marketing teams work.
A sync usually has four parts:
- A model built for syncing: one row per destination record, with a stable key that both systems share, such as the CRM account id.
- A field mapping from model columns to destination fields.
- A schedule or trigger. The tool compares the model with what it sent last time and sends only new or changed rows, using the destination’s upsert API keyed on the external id.
- Error handling for API rate limits, partial failures and retries.
Dedicated tools (Hightouch, Census and others) handle the diffing, mapping and API work; small teams sometimes write it themselves with API clients.
Because the output now reaches customer-facing people directly, data quality becomes operational: a wrong score is acted on within hours. Gate syncs on tests, decide which system owns each field so the CRM and the warehouse do not overwrite each other, and send only fields that consent and privacy rules allow. Compared with CDC, the direction is reversed: CDC moves operational changes into analytics, reverse ETL moves analytical results into operations.
Example
The diff a sync performs: compare today’s model with the snapshot of the last successful sync and send only the rows that changed.
CREATE TABLE account_health (external_id text PRIMARY KEY, health_score int, risk text);
INSERT INTO account_health VALUES
('001A', 82, 'low'), ('001B', 41, 'high'), ('001C', 67, 'medium');
CREATE TABLE last_synced (external_id text PRIMARY KEY, health_score int, risk text);
INSERT INTO last_synced VALUES ('001A', 82, 'low'), ('001B', 55, 'medium');
-- Rows to upsert in the CRM: new accounts and accounts whose fields changed.
SELECT m.external_id, m.health_score, m.risk
FROM account_health m
LEFT JOIN last_synced s USING (external_id)
WHERE s.external_id IS NULL
OR (m.health_score, m.risk) IS DISTINCT FROM (s.health_score, s.risk)
ORDER BY m.external_id;
external_id | health_score | risk
-------------+--------------+--------
001B | 41 | high
001C | 67 | medium
Common mistakes
- Syncing untested data into tools customers or salespeople rely on.
- No stable matching key, so each sync creates duplicate records in the CRM.
- Ignoring the destination’s API limits and sending every row on every run instead of only changes.
- Letting both systems edit the same field, which leads to endless overwrite loops.

