Schedule icon
Query icon
Query icon
Queries icon
If icon
Pause icon
Queries icon
Log icon
Assert icon
SlackIncomingWebhook icon

Reconcile MySQL to PostgreSQL Migration Parity and Synchronize Sequences for Cutover

Reconcile MySQL and PostgreSQL tables in DuckDB, detect replication drift, and synchronize PostgreSQL serial sequences for cutover in Kestra.

Categories
Data

Migrating production workloads from MySQL to PostgreSQL (such as Amazon Aurora MySQL to Aurora PostgreSQL, Supabase, or Neon) frequently encounters a subtle, catastrophic production outage during application cutover: duplicate key collisions on auto-incrementing primary keys. Change Data Capture (CDC) replication tools like Debezium, Airbyte, or pgloader replicate table data, but they do not automatically advance PostgreSQL SERIAL or IDENTITY sequence counters. When the application redirects write traffic to PostgreSQL, the first INSERT attempts to allocate id = 1, resulting in immediate unique constraint violations (Key (id)=(1) already exists).

This blueprint orchestrates an end-to-end migration parity audit and cutover gate. It discovers all tables in MySQL and PostgreSQL, computes exact count(*) values across both engines using dynamic UNION ALL scans, resolves sequence linkages across both SERIAL and modern IDENTITY columns, joins schemas inside an in-memory DuckDB database, flags row count drift, pauses for DBA verification, automatically computes setval sequence alignment statements, and applies sequence cutovers before certifying the migration in Slack.

How it works

  1. list_mysql_tables (io.kestra.plugin.jdbc.mysql.Query) queries information_schema.TABLES and auto-increment column definitions to discover all base tables in the source MySQL database.
  2. exact_count_mysql_tables (io.kestra.plugin.jdbc.mysql.Query) executes a unified UNION ALL scan computing exact count(*) values and un-cached MAX() auto-increment high-water marks for tables with auto-increment columns.
  3. inspect_postgres_catalog (io.kestra.plugin.jdbc.postgresql.Query) connects to target PostgreSQL and discovers all base tables, resolving sequence linkages for traditional SERIAL sequences (nextval(...)) and PostgreSQL 10+ IDENTITY columns (is_identity = 'YES').
  4. exact_count_postgres_tables (io.kestra.plugin.jdbc.postgresql.Query) executes a parallel UNION ALL scan across all target PostgreSQL tables to calculate exact live table row counts.
  5. reconcile_migration_parity (io.kestra.plugin.jdbc.duckdb.Queries) mounts JSON outputs via inputFiles with {{ workingDir }} path references. A SQL FULL OUTER JOIN compares exact row counts across all tables and identifies sequence lag, generating SELECT setval(...) statements and exporting migration_parity_reconciliation.csv to Kestra internal storage.
  6. sync_postgres_sequences (io.kestra.plugin.core.flow.If) evaluates whether unsynced sequences exist and cutover is enabled (apply_sequence_cutover: true, dry_run: false). It enters pause_cutover_approval (io.kestra.plugin.core.flow.Pause) with behavior: FAIL and a configurable pauseDuration (PT15M) to require human approval before executing the sequence batch via execute_sequence_cutover (io.kestra.plugin.jdbc.postgresql.Queries).
  7. certify_cutover_gate (io.kestra.plugin.core.execution.Assert) evaluates conditions asserting zero row count mismatches and zero missing target tables before authorizing production cutover.
  8. dispatch_cutover_report (io.kestra.plugin.slack.notifications.SlackIncomingWebhook) formats reconciliation metrics into a structured Slack message linking the reconciliation CSV artifact.

What you get

  • Heterogeneous schema reconciliation comparing exact MySQL and PostgreSQL row counts without statistical estimation drift.
  • Comprehensive sequence coverage across both legacy PostgreSQL SERIAL and modern IDENTITY columns (GENERATED ALWAYS AS IDENTITY).
  • Configurable approval pause gate (pauseDuration: PT15M) allowing DBAs to review reconciliation diffs prior to sequence mutations.
  • Safe default configurations (apply_sequence_cutover: false, dry_run: true) preventing accidental modifications during discovery runs.
  • Downloadable CSV audit reports preserved in Kestra execution storage for engineering compliance and sign-off records.

Who it's for

  • Database Administrators (DBAs) managing MySQL to PostgreSQL platform migrations and maintenance windows.
  • Data Engineers running CDC pipelines that need sequence alignment prior to application cutover.
  • Platform Engineers responsible for zero-downtime database migration runbooks.

Why orchestrate this with Kestra

Heterogeneous database cutovers involve coordinating multiple database engines under tight maintenance windows. Manual SQL inspection across MySQL and PostgreSQL terminals is error-prone and lacks reproducible execution logging. Kestra coordinates JDBC connections across different database engines in a single declarative YAML workflow, uses DuckDB for fast in-memory joins between disparate database catalogs, generates audit artifacts, pauses for DBA review, and safely automates sequence adjustment with assertion gates.

Pitfalls

  • Long Scans on Multi-Million Row Tables: Exact count(*) scans perform full table sequential reads. On very large tables (>50M rows), schedule this audit during dedicated low-traffic maintenance or cutover windows.
  • Active Write Drift: If replication is actively running and source writes have not been paused, table row counts may slightly diverge between the MySQL scan and PostgreSQL scan. Ensure application writes are drained or paused when validating cutover readiness.
  • PostgreSQL Sequence Permissions: Ensure the database user configured in postgres_user possesses USAGE and UPDATE privileges on all schema sequences to permit setval execution.

Prerequisites

  • MySQL source instance with read access to information_schema.TABLES and table data.
  • PostgreSQL target instance with privileges to query information_schema, pg_sequences, and execute setval.
  • Secrets configured in Kestra namespace settings: MYSQL_PASSWORD, POSTGRES_PASSWORD, and SLACK_WEBHOOK_URL.

Quick start

  1. Import this blueprint into your Kestra instance.
  2. Set inputs.mysql_host and inputs.postgres_host to your migration database endpoints.
  3. Configure MYSQL_PASSWORD and POSTGRES_PASSWORD in your namespace secrets.
  4. Run an initial test execution with dry_run: true to inspect the generated migration_parity_reconciliation.csv report.
  5. During your cutover window, set dry_run: false and apply_sequence_cutover: true to review the reconciliation diff, approve the pause gate, and align sequences for cutover.

How to extend

  • Table-Level Checksumming: Extend the DuckDB query to compute and compare MD5 or SHA-256 row hashes across primary key ranges for high-criticality financial tables.
  • Application Traffic Switching: Add downstream Kubernetes or Route53 tasks to automatically update application database service endpoints following successful sequence alignment.
  • Foreign Key Constraint Validation: Append a post-sync PostgreSQL verification task to check that foreign key constraints can be validated (ALTER TABLE ... VALIDATE CONSTRAINT) after data loading completes.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.