Incremental CDC from Database Using Managed Connector

Estimated read: 10 min

Where the previous lecture’s query-based connector polls and infers what changed, a CDC-based connector reads the database’s own change stream directly – seeing every insert, update, and delete as it happens, with no cursor-column blind spot.

What CDC actually reads

For MySQL, this means the binlog (binary replication log); for Postgres, logical replication (via a replication slot); for SQL Server, CDC tables or the transaction log, depending on configuration. In every case, the source database is already generating this stream for its own replication purposes – the connector reads it, rather than the connector generating extra query load against the live database the way polling does.

Setting up a CDC connection

CREATE CONNECTION mysql_cdc_connection
TYPE mysql
OPTIONS (
  host secret('db-creds', 'host'),
  user secret('db-creds', 'cdc_user'),
  password secret('db-creds', 'cdc_password')
);

The database user for CDC typically needs elevated replication privileges – REPLICATION SLAVE/REPLICATION CLIENT on MySQL, REPLICATION role on Postgres – distinctly more access than a read-only query user needs. This is worth flagging explicitly to whoever administers the source database; it’s a real conversation to have, not a checkbox.

The gateway

CDC-based ingestion typically runs through a gateway process – a component that connects to the source’s replication stream and stages changes before they’re processed into your bronze table. This is more infrastructure than the query-based pattern’s simple polling, which is the tradeoff for getting delete visibility and lower latency.

flowchart LR
    DB[(Source DB<br/>binlog / replication)] --> GW[CDC Gateway]
    GW --> Stage[Staging]
    Stage --> B[bronze.orders<br/>with _change_type column]

What lands in bronze, differently from query-based

DESCRIBE bronze.orders_cdc;
-- order_id, customer_id, order_total, ..., _change_type, _commit_timestamp

CDC-sourced bronze tables include a _change_type column (insert, update, delete) – explicit, per-row change semantics the query-based pattern simply can’t provide. This is directly what enables accurate SCD Type 2 modeling in silver (Section 7, and hands-on again in Part 2’s StepRight silver layer): a delete change type can close out a dimension record’s current-version flag correctly, something a query-based source has no signal for at all.

CDC vs. query-based: the decision in one line

If you need accurate deletes, near-real-time latency, and the source database team can grant replication-level access – use CDC. If deletes don’t matter for your use case, replication access isn’t available, or setup simplicity matters more than latency – query-based is the pragmatic default. Neither is universally “better”; they trade setup complexity and source access requirements for delete visibility and latency.


| ← Previous: Incremental Ingestion from Database Using Query Based Connector | Next: File-Based Ingestion with Auto Loader → | |:—|—:|


Back to top

Independent, self-authored Databricks companion notes.

This site uses Just the Docs, a documentation theme for Jekyll.