Data Warehouse Insider

CockroachDB Change Feeds vs Postgres Logical Replication for CDC

CockroachDB's distributed streams beat Postgres slots on operations but trade query flexibility.

· 9 min read
Cover illustration for “CockroachDB Change Feeds vs Postgres Logical Replication for CDC”
Database Replication Internals · October 20, 2026 · 9 min read · 1,921 words

CockroachDB changefeeds and Postgres logical replication differ first at the storage layer, and that difference determines their CDC trade-offs. Distributed range-based streams and a single WAL tap differ in what they need to keep running, handle schema evolution, and run a pipeline. Neither removes the need for downstream delivery logic, which teams can build themselves or delegate to a managed service such as Artie.

How CockroachDB and Postgres each produce a change stream, and why the storage layer explains everything downstream

Postgres logical decoding converts the server’s write-ahead log into row-level change events. An output plugin such as the built-in pgoutput delivers those events in commit order through a replication slot, with the whole instance as the replication unit. Before a CDC tool can connect, the server requires wal_level = logical, max_replication_slots, and max_wal_senders in postgresql.conf. The stream therefore originates from the log of a single primary rather than from independently replicated portions of the data.

CockroachDB splits data into ranges replicated across nodes, using Raft consensus and a leaseholder per range. Its changefeeds connect to requests called rangefeeds that stay open and push changes as they happen. Self-hosted clusters need kv.rangefeed.enabled = true, while Basic and Standard cloud clusters have rangefeeds enabled by default. Changefeeds are built into the database engine and send row-level changes directly to sinks including Kafka, cloud storage, webhooks, Google Cloud Pub/Sub, Azure Event Hubs, and Amazon MSK. This distributed stream works without an external connector or a replication slot on a single primary, which affects delivery guarantees, the work needed to run it, and how it handles schema changes.

What delivery guarantees each system actually provides, and where exactly-once remains an application responsibility

Both systems have at-least-once delivery by default, so a consumer must be able to handle the same event more than once. CockroachDB Core Changefeed provides at-least-once delivery, while Enterprise Changefeed adds resolved checkpoints. These resolved timestamps mark progress and let consumers reason about completeness. CockroachDB also provides per-key ordering, so changes to the same row arrive in order across its distributed range topology. Ordering and progress markers alone cannot ensure exactly-once delivery at the destination.

Postgres uses the LSN, or log sequence number, as its checkpoint mechanism. Safe processing follows a strict sequence in which the consumer reads an event, writes it to the target, waits for the target ACK, and then advances the LSN checkpoint. A crash between reading and committing can cause replay, while acknowledging before delivery breaks the safe checkpoint order. Downstream writes must therefore be idempotent in both systems, with inserts expressed as upserts, updates safe to repeat, and deletes that tolerate an already absent row. For warehouse pipelines using a managed service such as Artie, responsibility for exactly-once delivery without duplicates and checkpoint handling moves from consumer code to the service.

The operational cost Postgres hands to the operator — replication slots, WAL accumulation, and failover

A Postgres replication slot retains all WAL that its consumer has not confirmed. When a connector stops, that retained log can accumulate in pg_wal until the disk fills. Operators must check pg_replication_slots for active = false entries and large amounts of retained WAL, and drop slots that are no longer used. Setting max_slot_wal_keep_size bounds retention by allowing a dead slot to be invalidated. That exchanges an uncontrolled storage risk for a bounded failure that still requires recovery.

Failover adds a separate, version-dependent responsibility. On Postgres 17 and later, logical slots survive failover when created with the failover option and the required synchronization settings. The standby needs sync_replication_slots = on, hot_standby_feedback = on, and primary_slot_name set to a physical replication slot, while the primary needs synchronized_standby_slots configured. On Postgres 16 and earlier, preserving continuity requires an extension such as pg_failover_slots or manual standby-slot synchronization. Without that protection, when the primary is lost, its CDC slot is lost too, so the pipeline must be rebuilt or left with a gap in the stream.

These duties make source maintenance part of both CDC operation and database administration. Artie handles slot lifecycle, WAL management, and failover transparently, removing that operational work from the pipeline team. For teams operating their own consumers, control over the stream comes with responsibility for its retained state and recovery path.

The operational constraints CockroachDB's distributed CDC model introduces in exchange for removing the single-slot failure mode

CockroachDB keeps CDC running without the risk of single-slot WAL accumulation or the need for a primary-node failover procedure. With its Raft model, the stream can keep running when a node is lost without rebuilding a slot on a replacement primary. A write needs Raft quorum and at least one network round trip, including a cross-region round trip when quorum crosses regions. A Postgres write uses a local WAL append and fsync, so strict write-latency budgets remain a material distinction.

The distributed model also has limits at the query and job layers. CDC queries apply to only a single table per changefeed statement, and a query-based changefeed does not fully support ALTER CHANGEFEED. Its options can change, but its target tables cannot, and creating one on a table with more than one column family is unsupported. Cockroach Labs recommends no more than 80 changefeeds per cluster, so teams with many tables need to plan how to consolidate them. Operations such as TRUNCATE, DROP TABLE, and adding a column family can also cause errors in feeds watching those tables and need someone to step in.

How schema changes travel through each system, and where pipelines break in production

Postgres does not include DDL statements such as CREATE, ALTER, and DROP in its logical replication stream, although TRUNCATE is included from PostgreSQL 11 onward. The consumer therefore gets no in-band schema-change event to tell it that a column was added or a type changed. The pipeline must detect schema drift and coordinate its response out-of-band. Teams can plan migrations to work with that separation, but logical replication does not coordinate the work for them.

CockroachDB Enterprise Changefeed instead exposes a configurable schema-change policy, with stop, backfill, and nobackfill as choices. The schema_change_events option can also be set to column_changes. Changes to the database schema, including columns, indexes, and constraints, run online in the background without locking tables. However, a non-blocking database migration does not guarantee an uninterrupted changefeed job, because many DDL operations still cause feed errors and require a restart. Once the pipeline decides how to respond to a schema change, it must also encode the resulting events in a format its consumers understand.

Output format choices and what native Protobuf support changes for teams standardizing on typed messaging

CockroachDB changefeeds support JSON, Avro, CSV, Parquet, and Protobuf. Postgres logical decoding output depends on the plugin, with pgoutput producing a binary protocol that consumer libraries typically decode into JSON or Avro. Postgres has no equivalent native Protobuf output, so typed binary serialization belongs in consumer code or a separate transformation stage.

For CockroachDB teams already using Protobuf across Kafka consumers, native output removes the service that previously translated JSON or Avro events into Protobuf. That removes the translation layer’s latency, cost, and operational complexity. A permissively licensed .proto definition in a public repository gives producers and consumers a shared, versioned contract.

Protobuf bytes are not canonical, however, and serialized output is not stable across languages or versions. Teams must not use the serialized payload as a key or hash, and should use explicit key fields instead. Envelope choice is a separate decision. The bare envelope is most compact and suits internal services that do not need before-images, while wrapped adds change time, MVCC timestamp, topic, and key metadata and is recommended for production.

Compliance and data residency requirements, and which system's architecture makes them easier to satisfy natively

For regulated workloads, the distinction is between controls supplied by the database and controls assembled around it. Postgres provides RBAC, TLS in transit, and row-level security, with audit logging available through the pgaudit extension. Encryption at rest belongs to the operating system or cloud provider. For PostgreSQL, compliance certifications likewise depend on the managed service provider. These boundaries determine which parts of the compliance design the database can supply directly.

Geofiltered changefeeds use crdb_region in CDC query WHERE clauses to restrict events to data physically located in a specific region. Postgres has no equivalent native construct for geographic containment of change streams. For a HIPAA audit trail, a CockroachDB changefeed into cloud storage can supply the trail natively, while a Postgres implementation assembles it from pgaudit output, WAL archives, and managed-service audit logs. These are structural differences in how requirements are met, rather than a reason to treat every deployment of either database as having the same compliance posture.

Connecting either source to a managed replication service instead of operating CDC infrastructure directly

The database determines how changes leave storage, but the pipeline determines how they reach a usable destination. With either source model, teams still have work to do on deployment, schema evolution, exactly-once delivery, and failure recovery. A managed replication service treats these as shared infrastructure responsibilities. The ownership decision is therefore broader than whether to run a connector. It includes who maintains the delivery contract when the source, target, or schema changes.

Artie is a managed real-time CDC replication service that streams changes from Postgres and other operational databases to cloud data warehouses with sub-minute latency and exactly-once delivery. Its destinations include Snowflake, BigQuery, Redshift, Databricks, and ClickHouse. The service handles schema evolution, failure recovery, and fan-in architectures without requiring teams to build connector, retry, or schema-evolution code. It is designed to be deployable in under an hour and operates as a passthrough without storing customer data, which is relevant to teams with HIPAA or SOC 2 requirements.

AWS DMS also supports a managed approach. AWS describes it as supporting database and data warehouse migrations to and from AWS, continuous replication, and database consolidation. Its continuous replication supports low-latency movement between supported sources and targets, including on-premises targets, so it is not limited to one-time migrations. These managed approaches sit beside self-operated CDC, with the source mechanism still defining the constraints that each pipeline must handle.

Which architecture to choose, mapped to the workload characteristics that drive the decision

The choice turns on five workload characteristics, namely write-latency tolerance, failover requirements, schema change frequency, format standardization, and compliance posture. Postgres logical replication fits an existing Postgres workload where local write latency matters and migrations follow a controlled process. Postgres 17 or later makes native failover slot support available, provided the required synchronization is configured. A team that runs its own pipeline also needs to watch slots, limit WAL retention, and keep its consumers idempotent.

CockroachDB changefeeds fit an existing CockroachDB deployment or a new distributed SQL workload requiring multi-region availability. The trade is strongest when removing single-primary CDC recovery and WAL accumulation is worth the quorum write latency. Resolved checkpoints, configurable schema-change policies, and native Protobuf support also matter when they match the pipeline’s requirements. Regulated workloads needing CMEK, geofiltered streams, or native compliance certifications add further reasons to evaluate that architecture. Its query limits and DDL restart requirements still belong in the decision.

In either case, source-native CDC is not a complete warehouse replication pipeline. With either source, the downstream pipeline still has to handle exactly-once delivery, schema evolution, and recovery. Teams can absorb that work when control justifies the cost, or use a managed service such as Artie when ongoing warehouse delivery is the primary requirement. The database sets the constraints, and the pipeline layer must satisfy them regardless of who operates it.

More in Database Replication Internals