Query icon
Capture icon
IonToJson icon
Script icon
Process icon
If icon
Fail icon
SlackIncomingWebhook icon
Pause icon
Queries icon
Log icon
Schedule icon

Repair SQL Server CDC Capture Instance Column Drift

Compare SQL Server CDC event fields with sys.columns and safely cut over to a verified replacement capture instance.

Categories
Data

Safety

An ALTER TABLE ... ADD COLUMN does not update an existing SQL Server CDC capture instance. Debezium continues emitting successful events with the old field set, so a replica can lose a column without an alert.

Guard What it stops
Real event versus sys.columns A quiet success when CDC payloads silently omit a source column
Read after Pause Applying a plan after another operator changed the capture instances
Second instance and post-change capture Cutting over to a capture table that still omits the added column
Final CDC metadata read Reporting success when the old instance was not actually disabled

How it works

  1. read_schema (io.kestra.plugin.jdbc.sqlserver.Query) reads the live source columns and the existing capture instance membership.
  2. capture_current (io.kestra.plugin.debezium.sqlserver.Capture) takes a bounded event window. current_event_json (io.kestra.plugin.serdes.json.IonToJson) and compare_current (io.kestra.plugin.scripts.python.Script) compare the emitted fields with the source catalog.
  3. A healthy event ends in protected_or_healthy. Drift alerts Slack. The disabled scheduled_sweep (io.kestra.plugin.core.trigger.Schedule) always forces the safe inputs.
  4. A write requires auto_remediate: true, dry_run: false and an approved approve_repair (io.kestra.plugin.core.flow.Pause). recheck_eligibility reads the source and capture counts again before create_repair_capture (io.kestra.plugin.jdbc.sqlserver.Query) calls sp_cdc_enable_table.
  5. probe_change makes the caller's narrow canary mutation. capture_repaired uses capture.instance.include.list to read only the replacement. compare_repaired fails the run if a source column is still absent, then cutover disables the old instance and verify_cutover reads the final state.

What you get

  • A detector based on the CDC payload itself, not a lag or row-count proxy.
  • A dry-run report with the exact missing fields and no writes.
  • A human-gated replacement capture instance, a canary event proof and an explicit cutover check.
  • A failed run when the replacement event or final CDC metadata does not match the requested recovery.

Who it's for

  • Platform teams running SQL Server CDC through Debezium.
  • Data engineers who need schema changes to reach consumers.
  • On-call operators repairing a silent CDC field loss with an execution record.

Why orchestrate this with Kestra

SQL Server exposes the capture metadata and Debezium exposes the event payload, but neither coordinates a stale-plan approval, a bounded canary, a replacement instance and a verified cutover. Kestra keeps those reads, the guarded stored-procedure call, the event proof and the Slack failure path in one execution.

Tested end to end

The test fixture runs Kestra 2.0.5 with plugin-debezium-sqlserver 2.0.5 and plugin-jdbc-sqlserver 2.1.0 against the pinned mcr.microsoft.com/mssql/server:2022-latest image. It includes healthy, drift dry-run, declined approval, remediation, repeat, ineffective-write, race, protected-table and lookalike cases with independent sqlcmd assertions.

Case Execution Result
Healthy control sxk03IdRWEcb8gQqXbdoQ 3 source columns and 3 emitted fields
Drift dry run 4a8orojJwh3nN1MigOwEyY 4 source columns, 3 emitted, notes missing
Approved remediation 3sxq8554qUDM8vvxi7PRFP Replacement emitted 4 fields and old instance was absent
Repeat 1fkPlsbSLbZRhgpLVlzHLU Replacement remained healthy with 4 fields
Declined approval 5bOqQNC2iqgvtv8T1qH8bo Drift remained and no write ran
Protected table 4tpFXIgWt9w1zm67qvktwX Drift detected and repair path unavailable
Race during Pause 1DzxoSGGB4UM57Y6yacVrS Failed before write after the plan became stale
Refused write 1rUTBqRM589pLklkMAUl6Y SQL Server refused the invalid canary mutation
Independent healthy 1fxTmHeDcO0FXr2HkLSwQC Healthy on a fresh fixture
Independent remediation 4QpllR2iD9fnbg47FO26uE Fresh replacement event carried notes

Prerequisites

  • SQL Server 2022 with CDC enabled on the target database and table.
  • A login that can read sys.columns, cdc.change_tables and cdc.captured_columns, execute sp_cdc_enable_table and sp_cdc_disable_table and mutate the supplied canary row.
  • Kestra 2.0.5 with the Debezium SQL Server, JDBC SQL Server, SerDes JSON, Python, Slack and core plugins.

Secrets

  • SQLSERVER_USERNAME and SQLSERVER_PASSWORD: the CDC operator login.
  • SQLSERVER_JDBC_URL and SQLSERVER_HOST: defaults of jdbc_url and hostname.
  • SLACK_WEBHOOK_URL: failure and drift alert destination.

Inputs

Input Type Default Purpose
jdbc_url STRING SQLSERVER_JDBC_URL secret JDBC connection for catalog and CDC writes
hostname, port STRING SQLSERVER_HOST secret, 1433 Debezium connection
database_name, schema_name, table_name STRING cdc_lab, dbo, orders Source table identity
capture_instance STRING dbo_orders Existing instance to inspect and later disable
repair_capture_instance STRING dbo_orders_repair New unique instance name
protected_tables STRING dbo.audit_log Comma-separated schema.table values (exact, case-insensitive match) that are audit-only
probe_sql STRING Update canary row 1 Narrow mutation after the new instance is created
auto_remediate BOOL false Enables the approval-gated write path
dry_run BOOL true Must be false for writes

Quick start

  1. Enable CDC on the database and table, then insert a canary row that the supplied probe_sql can update.
  2. Add the two secrets and set the JDBC, Debezium host, table and capture-instance inputs.
  3. Execute with auto_remediate: false and dry_run: true; inspect compare_current for the emitted and missing fields.
  4. For an approved repair, execute with auto_remediate: true and dry_run: false, approve approve_repair and inspect compare_repaired plus verify_cutover.

How to extend

  • Run one flow execution per tracked table, each with a stable state_name and a unique replacement capture instance.
  • Put audit or legal-hold tables in protected_tables. They are still compared and reported, with no repair branch.
  • Replace probe_sql with an application-safe canary update.
  • Add a downstream replica check after verify_cutover when the application must prove the new column survived the sink as well as the CDC source.

Limits: the guard proves the source event field set and the CDC cutover, not that a running downstream consumer has advanced to the new schema. The caller supplies the canary mutation.

Links

This blueprint was created by zkasuran.

See How

New to Kestra?

Use blueprints to kickstart your first workflows.