CockroachDB to PostgreSQL: How to Move Your Data
Move CockroachDB data into PostgreSQL with Airbyte. Why CDC is unavailable despite wire compatibility, choosing a cursor, and the default privileges trap.

Moving data from CockroachDB to PostgreSQL is one of those jobs that looks solved before you start it, because CockroachDB speaks the PostgreSQL wire protocol. You can point psql at it. Your Postgres driver connects without changes. So the reasonable assumption is that a Postgres replication tool will treat it like Postgres.
It will not, and the reason matters for how you set the pipeline up. Wire compatibility is about the client conversation, not the storage engine underneath. PostgreSQL exposes its write-ahead log through logical replication slots, which is what change data capture reads. CockroachDB has no equivalent surface for Airbyte to attach to. What you get instead is cursor-based incremental replication, and once you accept that, the rest of the setup is straightforward.
Setting up the source
Create a read-only SQL user in CockroachDB and grant it SELECT on the schema you intend to replicate. Then run ALTER DEFAULT PRIVILEGES for that schema. This is the step people skip, and it is the one that causes a sync to quietly stop covering new tables three months later. Without it, the grant applies only to tables that existed the moment you ran it. Anything created afterwards is invisible to the sync user, so new tables never appear in the catalogue and nobody notices until someone asks why a table is missing.
The connector is scoped to a single schema per source configuration. If your data spans several schemas, you create several sources. That is a mild annoyance in the interface but it has an upside: each one gets its own sync schedule and its own failure blast radius.
Choosing a cursor
Cursor-based incremental sync needs a column that only ever increases and is set on every write. An updated_at timestamp maintained by your application is the usual choice. A sequence-backed integer works if rows are never updated after insert.
Two failure modes are worth knowing before you commit. Rows updated without touching the cursor column will not be picked up again. And rows deleted in CockroachDB stay in PostgreSQL forever, because a cursor query has no way to observe a deletion. If your destination needs to reflect deletes, you will need a soft-delete column in the source and a downstream filter, or a periodic full refresh on the affected tables.
Loading into PostgreSQL
The destination side is unremarkable in the best way. Give the connector a database, a schema, and a user with CREATE and INSERT on that schema. Airbyte creates one table per stream and adds its own metadata columns alongside your data.
Pick your sync mode per stream rather than globally. Incremental append with deduplication gives you a table that mirrors current state in the source, which is usually what you want for entity tables like customers or orders. Plain incremental append gives you a history of every version Airbyte ever saw, which is what you want if the downstream consumer cares about how a record changed over time.
Frequently asked questions
Can I use CDC from CockroachDB to PostgreSQL with Airbyte?
No. The CockroachDB source is cursor-based only. CockroachDB has changefeeds of its own, but they are not what the Airbyte source reads, so the connector cannot replicate deletes or capture updates that leave the cursor column untouched.
Why does my sync miss tables I created recently?
Almost always the missing ALTER DEFAULT PRIVILEGES step. Grant it for the schema, then refresh the source schema in Airbyte so the new tables appear in the catalogue.
Can one connection cover multiple CockroachDB schemas?
No. Configure one source per schema. You can point all of them at the same PostgreSQL destination.
What happens to deleted rows?
They remain in PostgreSQL. Use a soft-delete flag in CockroachDB and filter downstream, or schedule a periodic full refresh on the tables where deletes matter.
Get your CockroachDB data into PostgreSQL
CockroachDB is a distributed database that behaves like PostgreSQL at the edges and nothing like it underneath, and the pipeline you build should reflect that rather than fight it. Nominate a reliable cursor, fix the default privileges once, and pick sync modes per stream.
If PostgreSQL is a staging point rather than the endpoint, the same source pattern applies to a warehouse. See PostgreSQL to BigQuery and PostgreSQL to Databricks for what changes when the destination is columnar.
Integrate with 600+ apps using Airbyte
Move data from 600+ sources into warehouses, lakes, and beyond. Set up pipelines in minutes with pre-built connectors and the Connector Builder.
