CockroachDB
The CockroachDB source uses a core (sinkless) changefeed, which needs no enterprise license and no Kafka or cloud-storage sink. The snapshot is a consistent read at the changefeed's starting timestamp.
Prerequisites
Changefeeds need rangefeeds. If kv.rangefeed.enabled is false, the task tries to enable it; when the user may not change cluster settings, the task fails and asks an admin to run:
SET CLUSTER SETTING kv.rangefeed.enabled = true;
The table needs an explicit primary key. A table that only has CockroachDB's hidden rowid is refused with a hint to run ALTER TABLE … ALTER PRIMARY KEY USING COLUMNS (…).
A dedicated user
CREATE USER cdc WITH PASSWORD 'change-me';
GRANT SELECT, CHANGEFEED ON TABLE shop.public.products TO cdc;
Missing privileges fail the task with (the user needs SELECT and CHANGEFEED privileges on the table).
Connection string
CockroachDB speaks the PostgreSQL wire protocol; use a PostgreSQL URL with the database in the path:
postgresql://cdc:change-me@crdb.internal:26257/shop?sslmode=verify-full
postgresql://root@localhost:26257/shop?sslmode=disable # insecure local cluster
Task fields
| Field | Default | Meaning |
|---|---|---|
table | required | The table in the connection's database. |
schema (API only) | public | Schema of the table. |
How changes are applied
- Snapshot. Keyset pages of 5,000 rows read
AS OF SYSTEM TIMEthe position captured before the copy, so the copy is consistent and the changefeed continues exactly from there. - Stream.
CREATE CHANGEFEED FOR TABLE … WITH updated, resolved = '1s', format = json, cursor = '…'(older versions fall back toEXPERIMENTAL CHANGEFEED FOR). Rows are read as JSON in both phases, so they carry identical values: numbers become integers or floats,TIMESTAMP/TIMESTAMPTZbecome times, other values stay as CockroachDB renders them in JSON. - Deletes arrive as rows with a null
afterimage and delete the document. - Truncates are not captured by changefeeds; resync the task after a
TRUNCATE.
Positions and resume
Positions are CockroachDB HLC timestamps in decimal form, for example 1700000000123456789.0000000001. Changefeed rows are only ordered per key, so every event carries the latest resolved timestamp seen so far: everything at or before it has been delivered, and restarting from it replays at most a few changes.
A position older than the table's garbage collection window (gc.ttlseconds) cannot be resumed; the task resyncs automatically. Keep tasks running, or raise the TTL for tables whose tasks may be stopped for long.
Troubleshooting
| Error | Fix |
|---|---|
changefeeds need rangefeeds, but kv.rangefeed.enabled is false and this user cannot change it | Run SET CLUSTER SETTING kv.rangefeed.enabled = true as an admin. |
table public.x has no primary key (it uses the hidden rowid column) | Add a primary key. |
table public.x does not exist in the current database | Put the right database in the connection string. |