Apache Kafka change data capture with Debezium

Debezium source connectors on Kafka Connect stream row-level database changes into Kafka topics. This page covers the supported databases, deployment, topic layout and the snapshot, schema change and connector failure work that follows.

On this page

How Debezium streams database changes into Apache Kafka

Debezium is a set of log-based source connectors that read a database's change log and publish each insert, update and delete as an event to Kafka topics. Teams reach for it when downstream systems need database changes without polling application tables for modified rows, a pattern that misses deletes unless the schema is designed for them and adds query load to the production database. The Debezium project documents this integration, so use its documentation as the authority for connector versions and per-database settings. Apache Kafka has no change data capture engine of its own. Brokers store and serve records, and they do not read database logs. The Debezium connector runs inside a Kafka Connect worker, which schedules connector tasks, creates topics, and stores connector configuration and offsets.

Because the connector reads the *log* instead of repeatedly querying tables, the work on the source side is limited to enabling the logging the connector needs and granting it a read path to that log. Each change event describes a change to a row and where that change sits in the source log, and Connect stores the position so a restarted task can resume from its last recorded offset. Two runtime choices follow. Kafka Connect should run in distributed mode so connector tasks can move to another worker when one fails, and the workers need a Java runtime that matches the Kafka release, which is Java 17 for Kafka 4.x brokers, Connect and tools. The database engine version must also stay inside its support window for the whole planned run, so check that before the first connector is registered.

This page covers the parts of the integration that sit between the source database and the Kafka cluster: how the connector is deployed, how topics are laid out, and the operational work of snapshots, schema changes and connector failures. It does not repeat Kafka cluster installation or broker security, which are covered on their own pages. Before sizing anything, confirm three things with the Debezium documentation and your database vendor: which Debezium release supports your database version, which database settings the connector requires, and whether your team will run Connect on Kubernetes or on servers. Those answers set the order of the build.

What a Debezium deployment needs before the first connector starts

A Debezium source connector depends on four layers working together: a KRaft Kafka cluster, Kafka Connect workers, the source database configured for change capture, and the network and credentials that join them. Gaps in any one layer usually surface later as snapshot failures or lost change events, so confirm each card before deploying the connector.

KRaft cluster and Java runtime

Debezium runs as connectors on Kafka Connect, so the Kafka cluster must be up and healthy first. Kafka 4.0 and later supports only KRaft mode, so a ZooKeeper-era cluster must migrate before it can serve as the target. Kafka Connect workers on Kafka 4.x need Java 17. Check the broker and Connect versions against the Kafka upgrade notes, and confirm the exact Debezium release and its supported Kafka Connect version in the Debezium documentation for your environment.

Source database capture settings

Each Debezium connector reads changes from the database log, so the database must enable the logical decoding or binary logging settings that the Debezium connector documentation specifies for that database and version. Changing these settings often requires a restart of the database server, which should be scheduled. Confirm the required parameters and the supported database versions for your chosen connector in the Debezium documentation before you change production settings.

Dedicated capture account privileges

The connector needs a database account with the privileges Debezium documents for reading the transaction log, reading table structures and, for initial snapshots, reading the captured tables. Use a dedicated account rather than an administrator or a shared application login, and review the privileges again whenever you add tables or change the connector configuration. Record which account owns the replication slot or log position, because removing it can stop capture.

Network paths between Connect, brokers and database

Kafka Connect workers must reach the database listener and every Kafka broker address advertised in the cluster. Check that firewall rules, DNS names and load balancers allow these connections from each Connect worker, including after a broker or database failover. Confirm that the database permits replication connections from the Connect network segment, since capture uses a separate connection path from ordinary queries.

TLS certificates for every hop

Kafka supports SSL/TLS for traffic between clients, brokers and tools, and security is optional, so each listener must be configured deliberately. Issue certificates that Connect workers trust for both the brokers and the database, and plan renewal before expiry. Confirm which SASL mechanism the Connect worker uses, because the documented options include GSSAPI, PLAIN, SCRAM-SHA-256, SCRAM-SHA-512 and OAUTHBEARER.

Connect topics and ACLs in place

Before the first connector starts, Connect needs topics for its own configuration, offsets and status, and the cluster needs ACLs that let the Connect principal create or write the topics it uses. In KRaft clusters, the StandardAuthorizer stores these ACLs in the metadata log, and resources without ACLs are limited to super users unless allow.everyone.if.no.acl.found is set to true. Confirm the Connect principal can write its internal topics and the change topics before the connector is created.

Configuring the connector in the order that avoids snapshot surprises

This sequence prepares the source database, installs the connector plugin, configures Kafka Connect, registers the Debezium source connector and confirms that the initial snapshot and the streaming phase both produce events before any downstream consumer depends on them.

  1. Prepare the database user and replication settings

    The database administrator creates a dedicated Debezium user with read access to the tables in scope and the privileges the chosen connector documents for logical decoding. They enable logical replication on the source server and create or confirm a replication slot and publication plan with the DBA team. Confirm the exact privileges and server parameters against the Debezium documentation for your database version, since they differ by connector. The step is complete when a test login with the new user can read the target tables and the replication settings are visible in the server configuration.

  2. Install the connector plugin into the Connect plugin path

    The platform team places the Debezium connector plugin for the source database into a directory listed in the Connect worker's plugin.path setting, using the version that matches the Kafka Connect runtime you operate. Each Connect worker in the cluster needs the same plugin files, so install them with your image build or configuration management rather than by hand on a single node. Restart the workers as your deployment method requires. The step is complete when the Connect REST API lists the Debezium connector class among the installed plugins.

  3. Create the Connect worker configuration

    The platform team writes the distributed worker configuration with the bootstrap servers, the group.id, and the converter settings for keys and values. They define the three internal topics for offsets, configs and status, and set their replication factors to match the cluster's replication capacity, so that a broker loss does not erase connector state. Review the converter choice with the schema and consumer teams before the first connector is registered, because changing it later affects every topic the connector writes. The step is complete when the workers start, join the same group and report no errors for the internal topics.

  4. Register the source connector

    The integration owner submits the connector configuration through the Connect REST API. The configuration sets the connector class, the database hostname, port, user and credentials pulled from a secret store, a logical server name that prefixes every topic, and the table include list. Choose the topic naming convention with the consuming teams at this point, since topics are created from the server name and table names. Avoid listing tables you do not need, because each one adds snapshot work. The step is complete when the connector is accepted and appears in the list of connectors.

  5. Verify the connector status through the REST API

    Query the connector status endpoint and the status of each task in the Connect REST API. The connector and its tasks should report RUNNING, and the connector should not be in a FAILED state. If a task fails, read the error in the status response and the worker logs before restarting anything, because most failures at this stage come from database permissions, network reachability or a server parameter that was not applied. Record the status output in your change ticket. The step is complete when every task reports RUNNING on two consecutive checks.

  6. Confirm the initial snapshot completes

    Watch the snapshot phase in the connector logs and the topic offsets as the initial snapshot reads the included tables. Check that the row counts and the snapshot completion message match what the DBA expects for those tables, and note how long the snapshot ran in your environment so you can plan future snapshots. Confirm with the database owner that the snapshot load was acceptable for production traffic. The step is complete when the connector logs show the snapshot has finished and the snapshot events are present in each expected topic.

  7. Consume one change event from the topic

    Make a controlled change in a test row in one included table, such as an insert or update that the test team agreed on in advance. Consume the matching topic with a console consumer or a test client and confirm that the event contains the expected before and after values, the operation code and the source metadata. Check that the topic name follows the convention agreed in the registration step. The step is complete when the test event arrives with the expected structure and no unexpected fields.

  8. Confirm the streaming phase and record the baseline

    After the snapshot, confirm that new changes continue to stream without a restart and that the connector's source offset advances as the database changes. Record the connector configuration, the internal topic names, the plugin version and the first verified offsets in your runbook, so that operators can compare them during later incidents. Ask the vendor or project documentation which metrics to alert on for the connector before production traffic is connected. The step is complete when the streaming test passes and the baseline record is stored with the platform documentation.

How topic names, keys and partitions follow from the table layout

Debezium builds each change topic name from three parts: the logical server name configured for the connector, the schema, and the table. In practice that means a source table in a given schema produces one topic per table, and the server name becomes the prefix every downstream consumer must know. Decide the server name and naming convention before the first connector is deployed, because renaming topics later means re-pointing consumers, sinks and access rules. Confirm the exact naming behavior for your Debezium version and your database connector, since the separator and the handling of schemas differ between database types. For the PostgreSQL side, the publication and slot names you choose also belong in this naming plan so that operators can tell which connector owns which stream.

The message key comes from the table's primary key by default, so every change to a row lands on the same partition and Kafka preserves the order of changes for that row. That ordering guarantee holds only within one topic and one partition. A table without a primary key, or a key that changes over time, breaks the link between row identity and partition, and consumers can see updates before inserts. Per-table topics keep ordering scoped to each table and make partition planning a per-table decision: a high-volume table may need more partitions than a reference table, and the partition count cannot be lowered later without rebuilding the topic. Consolidated topics, built with routing or transforms, reduce the number of topics and partitions to manage but mix schemas and make per-table retention, access control and consumer logic harder to separate.

Choose the layout deliberately for each change topic, not by default. Retention on change topics determines how far back a new consumer can replay, and compaction keeps the latest state per key, which suits tables that are consumed as a current-state feed. Many teams use a mix: time-based retention for event-like tables and compaction for entity tables, with a written rule for each. Ask the platform team which default retention and cleanup policies they will enforce for topics created by Connect, since automatic topic creation can apply broker defaults that nobody reviewed. Document the layout alongside the connector configuration so that a table added later follows the same naming, key and retention rules.

How database column types and change events map to Kafka messages

This table compares each source database concept with what Debezium writes to Kafka, so you can check the message layout before you define topics and consumers. Read each row against your own database engine and connector version, since type handling and schema details vary. The main takeaway is that the key, the before and after images and the schema history decide how downstream consumers must parse and deduplicate events.

Source conceptWhat Debezium emitsWhat to confirm or plan
TableOne topic per captured table, named from the topic prefix, schema and table name by defaultConfirm the topic naming pattern and whether you will use topic routing transforms to rename topics
Row insertA create event (op c) with the new row in the after field and no before imageConfirm the op codes your consumers expect and that they handle the create event on first load
Row updateAn update event (op u) with the after image and, depending on row image settings, the before imageConfirm the replica identity setting on each source table, because it limits what the before image contains
Row deleteA delete event (op d) with the before image, followed by a tombstone record with a null value for compacted topicsConfirm your topics use compaction and that consumers treat tombstones as deletes
Primary keyBecomes the message key, so events for one row land on one partition in orderConfirm every captured table has a primary key or a unique key, since tables without one need extra configuration
Column data typesMapped to Kafka Connect logical and primitive types, with some types such as decimals, timestamps and JSON handled by connector settingsConfirm the type mapping for each column, especially numeric precision, time zones, enums and geometry types, against your connector version
Schema historySchema changes are recorded in a schema history topic, and the value schema is sent with each message when schemas are enabledDecide whether to use a schema registry or embedded schemas, and plan how consumers handle a schema change mid-stream
Transaction metadataOptional transaction boundary messages and event metadata fields, when enabled in the connectorConfirm whether your consumers need transaction markers and how they handle events that arrive out of commit order

Snapshots and schema changes: the operational work after launch

When a Debezium connector starts on a table set for the first time, it normally reads the existing rows before it streams changes, so consumers receive the current state as well as later changes. The read is a full scan of each included table, while the connector records the log position it will stream from once the read finishes. Snapshot time depends on table size and source capacity, so measure it in a non-production copy of the database before scheduling the first run.

  • Read load: The snapshot runs large reads against production tables. Limit scope with table include lists and agree a run window with the database owners.
  • Consistency point: The connector captures a consistent position so changes made during the read are streamed afterward. Confirm the locking and isolation behavior for your PostgreSQL version and the privileges the connector user needs.
  • Replication slot and WAL: On PostgreSQL, the logical replication slot holds write-ahead log until the connector confirms it. A long snapshot grows disk use on the primary, so watch the size of pg_wal and free disk space before starting.
  • Consumer tolerance: Consumers see a burst of read events followed by ordinary change events. Treat reads as upserts keyed by primary key, and expect duplicates if the connector restarts during the run.
  • Test: Run the snapshot against a copy, record duration and peak load, compare row counts per topic with source counts, and rehearse a stop and restart in the middle of the run.

Before the first run, confirm that the database owners have approved the window, that disk headroom covers the slot, and that the expected row counts are written down.

Securing the database account, Connect workers and change topics

Debezium connectors touch three trust boundaries: the source database, the Kafka Connect workers and the Kafka topics that carry the changes. Each boundary needs its own account, encryption and access rule, and the controls below should be designed together before the first connector goes live.

Least-privilege database account

Create a dedicated replication user for each connector with read access only to the tables in scope and the replication privileges the connector needs. Avoid reusing an application or administrator account. Check that the grants cover the included tables and nothing else, and record who approves changes to them. Confirm the exact privileges required for your database version with the Debezium connector documentation before granting them.

Encrypted connection to the database

Require TLS between the Connect workers and the source database, and verify the server certificate rather than trusting any certificate presented. Change data often includes personal and financial fields, so unencrypted replication traffic exposes the same values the topics later hold. Confirm the TLS mode options your database driver supports and test that connections fail when the certificate does not match.

Client authentication to Kafka

Choose SSL or one of the documented SASL mechanisms for the Connect worker principal, such as SCRAM-SHA-512 or OAUTHBEARER, and encrypt the connection with TLS. Kafka security is optional, so a listener left unsecured will still accept the connector unless you disable it. Give each worker its own principal so its activity can be traced and revoked independently.

ACLs on change topics

In KRaft clusters the StandardAuthorizer stores ACLs in the metadata log, and resources without ACLs are limited to super users unless allow.everyone.if.no.acl.found is set to true. Grant the connector principal write access only to its own topics and the schema history topic, and grant read access to named consumer groups. Because change topics carry personal or financial data, review who holds read rights on them as carefully as on the source table.

Secrets in connector configuration

Connector configuration holds database passwords, keystore passwords and Kafka credentials. Keep them out of plain connector JSON stored in version control and use an externalized secrets mechanism supported by your Connect deployment, so the REST API returns references rather than values. Rotate credentials on a schedule and confirm that rotation restarts the affected tasks cleanly.

Connect REST API access

The Connect REST API can create, pause, restart and delete connectors, so anyone who reaches it can change what leaves your database. Restrict it to the platform team's network segment, require authentication in front of it, and log every change. Treat a connector deletion or offset reset as a privileged action that needs the same approval as a schema change.

Connector failures, causes and first fixes

This table lists the failure points most often seen with Debezium source connectors on Kafka Connect, with the likely cause, the first check and the direction of the fix for each. Use it as a triage starting point, then confirm exact states, parameters and recovery steps in the Debezium troubleshooting guidance for your connector and database version.

Failure pointLikely cause and first checkFix direction
Connector task in FAILED state after a database restartThe task lost its database connection or failed to resume streaming. Check the task status and the Connect worker log for the first exception, then confirm the database accepts connections from the worker.Restart the failed task after the database is healthy, and confirm the connector resumes from its stored offset. Confirm the restart behavior in the Debezium troubleshooting guidance.
Replication slot or binlog position unavailableThe slot was dropped, or the log position the connector stored was purged by the database. Check that the slot exists in PostgreSQL or that the binlog file named in the stored offset still exists in MySQL.Recreate the slot or re-snapshot the affected tables only after confirming the data gap is acceptable. Retention settings on the source database determine how long a stopped connector can wait.
Missing permissions after a schema changeThe connector user lacks read or replication privileges on a new table or column, or the schema change was not visible to it. Check the connector error for a permission denial and compare grants with the table list.Grant the documented privileges to the connector user for the new objects and restart the task. Review the grant requirements for your database in the Debezium documentation.
Topics not created or auto-creation disabledThe broker has topic auto-creation turned off, so Debezium cannot create change event topics. Check the connector log for unknown topic errors and the broker setting for auto-creation.Create the topics ahead of time with the planned partition count and retention, or enable auto-creation for the connector's topics. Align topic naming with the layout decided for the pipeline.
Offset loss on Connect internal topicsThe offset, config or status topics were deleted, compacted incorrectly or created with the wrong replication settings. Check that the Connect internal topics exist and that their replication factor and cleanup policy match the Connect documentation.Restore the internal topics with the required settings and reconfigure the connector. Stored offsets for source connectors live in these topics, so a loss can trigger a re-snapshot. Confirm the required settings in the Kafka Connect documentation.
Serialization errors from unexpected column typesA column type the converter or Debezium mapping does not handle, such as a new custom or complex type, produces an error during conversion. Check the task log for the column name and the converter exception.Adjust the type mapping or converter settings, or exclude the column with a filter, then restart. Test new column types in a non-production environment before they reach a live connector.
Consumer lag caused by large snapshotsA initial or re-snapshot of large tables publishes a high volume of events in a short period, so consumers fall behind. Check snapshot progress in connector metrics and consumer lag on the affected topics.Scale consumers or partition counts for the affected topics, or schedule snapshots outside peak hours. Confirm snapshot modes and their effect on load in the Debezium documentation.

Questions teams ask before running Debezium on their own

Can our team run Debezium on its own without outside help?

Yes, a team that already operates Kafka Connect and has direct access to the source database can usually run Debezium in-house, but the first connector takes the most work. Someone must understand the source database's replication settings, someone must run Kafka Connect and its topics, and someone must own the downstream consumers. Teams that have only operated Kafka brokers often underestimate the database side. Before deciding, have your team build one test connector and run a snapshot and a schema change against it. Those two events expose most of the operational gaps. DeployOpen can plan, implement, document and hand over a Debezium deployment inside your infrastructure under a written scope, so your staff can operate it afterward.

What drives the effort of a Debezium deployment?

The effort depends on how much change data flows through the platform and how many teams depend on it. The main drivers are:

  • The number of source databases and their engine versions
  • The number of tables captured per connector and whether they include wide or very large tables
  • How often source schemas change and how those changes reach consumers
  • The number of consumer applications that read each topic and their tolerance for delay or duplicate events
  • How much Kafka Connect operations work your team already performs, such as deployments, plugin management and monitoring

A single small database with stable tables is a contained project. Many databases with frequent schema changes and many consumers take considerably more design and testing. Ask any provider to break its estimate down along these drivers.

How many steps does a Debezium setup involve?

A Debezium setup is a sequence of steps, and each step has a clear exit condition. The typical sequence is:

  • Confirm the source database version, replication configuration and backup position
  • Create a dedicated database account with only the privileges the connector needs
  • Deploy Kafka Connect on a supported Kafka release with the Debezium source connector plugin
  • Define topic naming, partitioning, retention and schema handling for captured tables
  • Run a test connector through an initial snapshot, then through inserts, updates, deletes and a schema change
  • Validate event contents with the consumers that will read them
  • Add monitoring, alerts and runbooks, then move the connector to production

The exact duration depends on your database count, your approval process and how quickly your teams review test results. Ask for the step list and the review points in the written scope.

What does the work need from database and platform teams?

The database team controls the settings that let change capture read the write-ahead log, so it must be involved from the start. For PostgreSQL, that includes the wal_level setting, the number of replication slots and senders available, and the privileges granted to the connector account. The platform team controls the network paths from Kafka Connect to each database, the secrets store for credentials, Kafka ACLs for the connector and its topics, and the capacity of the Connect cluster. Both teams must agree on who approves schema changes, because a column change in a source table can change the events downstream. Confirm these responsibilities, and the change window for replication settings, before the build starts.

Does Debezium or Kafka licensing add cost?

Apache Kafka is licensed under the Apache License 2.0, and the Apache Software Foundation project offers no paid edition, so the software itself adds no license fee. PostgreSQL uses the PostgreSQL License, a permissive license similar to the BSD and MIT licenses. Debezium and any Kafka Connect distribution or plugin packaging you choose must be checked separately. Confirm the license of each Debezium component you deploy in its own project documentation, and confirm the terms of any commercial support or packaged distribution from a vendor. The recurring costs are usually infrastructure, staff time and support, not the license of the open-source components themselves.

Which Kafka and Java versions should a new Debezium deployment target?

Target a Kafka release that is still supported. The Kafka downloads page lists 4.3.1, 4.2.2 and 4.1.2 as supported releases, and all earlier versions are archived. Since Kafka 4.0, brokers, Kafka Connect and tools require Java 17. Kafka 4.0 also supports only KRaft mode, so a new deployment should use KRaft from the start. Check which Debezium release supports your chosen Kafka and Connect versions in the Debezium documentation before you pin versions. Set a plan for upgrades, because supported Kafka releases receive bugfix updates only for a limited period and the Kafka release plan describes which upgrade paths are supported.

How is the cost of a Debezium implementation quoted?

A quote follows from a written scope. DeployOpen agrees the scope, deliverables and timeline in writing before work starts, and most engagements are fixed in this way. The scope should name the source databases, the table counts, the consumers, the environments and the handover tasks. The quote usually separates one-time work, such as design, build, testing and documentation, from recurring work, such as monitoring, upgrades and support, which can be offered as a retainer. Ask each provider which items are included, which depend on your staff being available, and which are priced as options. DeployOpen does not publish a price list, so ask for a quote against your written scope.

Running Debezium day to day with upgrades and monitoring

Keep the connector current by treating the Kafka Connect worker and the Debezium connector plugin as two upgrades with separate test gates. Since Kafka 4.0, brokers, Kafka Connect and tools require Java 17, so check the worker JVM before anything else. The Kafka downloads page lists 4.3.1, 4.2.2 and 4.1.2 as supported releases, and the project aims for three releases a year, one every four months. The time-based release plan supports rolling upgrades from each of the last three releases to the latest, which gives you a window to move the worker in steps. Confirm in the Debezium documentation which connector versions support your Kafka release before you schedule the change, because that compatibility is not covered by the Kafka sources used for this page.

Monitoring has two parts: connector state and source position. Query the Kafka Connect REST API for the status of each connector and task, and alert on any task in FAILED state or on a restart loop, since a failed task stops capture without any error reaching the consumers. Track the offsets stored in the Connect offset topic, because they determine where a restarted connector resumes in the database log. On the database side, a stopped connector can leave a logical replication slot holding back write-ahead log, so watch slot lag and disk use on PostgreSQL as well. Review each alert with the team that owns the connector, and confirm which status fields and metrics your Debezium version exposes before you build dashboards on them.

Test every connector upgrade against a restored copy of the source database before production. Restore a recent copy of the PostgreSQL database into a separate environment, then run the upgraded worker and connector with a different topic prefix and their own offset and status topics. Replay representative inserts, updates, deletes and at least one schema change, and compare event counts, key ordering and field layout with production output. Keep a written owner record for each connector that lists the source database and PostgreSQL major version, the Kafka and Debezium versions, the replication slot name, the topics it writes, the schema owner, the on-call contact and the rollback steps. Without that record, nobody can say who approves a snapshot restart or a schema change during an incident.

How DeployOpen scopes and delivers Debezium change capture

DeployOpen plans, implements, hardens, documents and supports self-hosted open-source platforms inside your own cloud accounts, data centers or air-gapped networks. For Debezium change capture, that means agreeing the source databases, connector topology, topic layout and operating runbooks in writing before the build starts.

How we scope

  • Inventory each source database, its version, replication settings and the tables that must be captured.
  • Agree topic naming, partition counts, key strategy and retention for every captured table in writing.
  • Define snapshot, schema change and connector failure runbooks as deliverables inside the fixed scope.

How we build

  • Deploy Kafka Connect and the Debezium connectors in your environment, using the Kafka version you have chosen.
  • Configure TLS and SASL authentication for connectors, with database credentials held in your secrets store.
  • Test snapshots, inserts, updates, deletes and a deliberate schema change against non-production data before go-live.

How we hand over

  • Deliver connector configurations, topic catalogue, ACL mappings and monitoring dashboards as versioned artifacts.
  • Walk your platform and database teams through restart, offset reset and snapshot procedures using their own environment.
  • Document the database-side prerequisites so your DBAs can review and own replication settings after handover.

How we support

  • Ongoing support, connector upgrades and continuous testing are available as retainers after handover.
  • Retainers can cover connector version reviews, lag alert tuning and recovery drills for captured databases.
  • Confirm with your team which support hours, response expectations and upgrade windows the retainer must include.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.