← All playbooks
Databases migration

MySQL → PostgreSQL

Move a production MySQL database into PostgreSQL while translating schemas, types, identifiers, SQL, constraints, indexes, views, procedures, users, application behavior, replication, performance, and recovery.

Typical timeline25–60 business days130–260 hours active work
Statusneeds review
Source testedMySQL documentation reviewed 2026-07-19
Destination testedPostgreSQL documentation reviewed 2026-07-19
Last reviewed2026-07-19
Sources3
Before you migrate

Should you make this move?

Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.

Current platform

MySQL

Reasons to stay
  • Ubiquity, operational familiarity, and broad hosting support reduce adoption risk
  • A mature data model and query ecosystem supports serious production workloads
Reasons to leave
  • Advanced SQL, extensibility, and consistency features can lag PostgreSQL
  • Schema design, migration, tuning, and operations require specialist attention
New platform

PostgreSQL

What gets better
  • Powerful SQL, extensions, integrity, and open governance support demanding workloads
  • A mature data model and query ecosystem supports serious production workloads
What gets worse
  • Tuning, upgrades, and sophisticated features require experienced operators
  • Schema design, migration, tuning, and operations require specialist attention
Best of the move

PostgreSQL: Powerful SQL, extensions, integrity, and open governance support demanding workloads. This removes a major source-side concern: Advanced SQL, extensibility, and consistency features can lag PostgreSQL.

Worst of the move

What you lose: Ubiquity, operational familiarity, and broad hosting support reduce adoption risk. What you inherit: Tuning, upgrades, and sophisticated features require experienced operators.

01At a glance

Know the shape of the move.

Transfer outcome12 features audited
Transfer outcome distributionClean transfer: 0, Partial transfer: 5, Manual rebuild: 7, Not transferred: 0.
Clean0
Partial5
Manual7
Lost0
Mapping route9 of 9 fields have a destination path

This timeline assumes

  • Up to 500 tables, 1 TB of data, 200 critical queries, and a 30-minute write-freeze objective
  • Application and data owners approve a versioned target schema and consistency strategy.
  • A production-shaped snapshot and write workload are available for rehearsal.
  • The source remains authoritative until lag reaches zero and all invariants pass.
  • The migration team records evidence for every blocking verification check.
02Loss matrix

What survives the move.

“Partial” and “manual” are not footnotes. They are work that must be scheduled and verified.

ItemOutcomeImpactWhat happensMitigation
MySQL types and automatic valuespartialcriticalUnsigned integers, tinyint booleans, zero dates, enum, auto-increment, collations, and timestamp behavior require explicit mappings.Build boundary fixtures and reject truncation or implicit fallback.
SQL syntax, functions, procedures, and triggersmanualcriticalMySQL dialect and stored logic do not execute unchanged in PostgreSQL.Inventory executed SQL and port it with behavioral tests.
Indexes, query plans, and lockingmanualcriticalEquivalent data and SQL can have different performance and concurrency behavior.Benchmark production-shaped reads, writes, transactions, and contention.
Online delta and application cutovermanualcriticalBulk loaders move snapshots; low-downtime writes require a separate change-capture plan.Rehearse snapshot, CDC, catch-up, freeze, connection switch, and rollback.
Schemas, collections, and tablespartialcriticalStructures require explicit relational, document, type, and naming decisions.Version a signed target schema before loading production data.
Rows, documents, and identifierspartialcriticalData can move while IDs, generated values, precision, encoding, and null semantics differ.Preserve stable source IDs and compare deterministic checksums and aggregates.
Types and nested valuespartialcriticalSource types may coerce, flatten, normalize, or move into JSON columns.Create type-level fixtures and reject silent truncation.
Relationships and referencespartialcriticalForeign keys, embedded documents, polymorphism, and cascades require redesign.Load parents first and verify orphan and cascade behavior.
Indexes and query behaviormanualcriticalIndex syntax and query planners differ.Design from production query evidence and benchmark representative workloads.
Constraints, defaults, and generated valuesmanualcriticalValidation and automatic behavior do not transfer with raw data.Recreate and test every business invariant.
Views, functions, triggers, and proceduresmanualcriticalSQL dialects and database runtimes differ.Port reviewed logic and test side effects and failure paths.
Users, roles, and permissionsmanualcriticalAuthentication and grants are platform-specific.Apply least privilege before application access.
03Field and feature mapping

Where each thing goes.

SourceDestinationMethodNotes
MySQL database or basePostgreSQL database or documentmanualRecord owner, region, collation, and source ID.
Schema, collection, or tableDestination schema and tabletransformApprove relational and naming semantics.
Row or document IDPrimary key and source IDtransformPreserve stable identity.
Source field or columnDestination columntransformMap type, null, default, precision, and encoding.
Nested object or arrayRelation, array, or JSONBtransformChoose query and integrity behavior explicitly.
Reference or foreign keyDestination foreign key or relationtransformCreate after parent records exist.
IndexDestination indexmanualDesign from query evidence.
View, formula, or generated valueDestination view, expression, or generated columnmanualRewrite and test output.
Trigger, automation, or integrationDestination trigger or application workflowmanualPort idempotently and test failure behavior.
04Before you begin

Make the move recoverable.

Backup procedure

Create the source-of-truth backup

Preserve MySQL data, configuration, and operating evidence before any destination write.

  1. Create a native, restorable MySQL backup plus logical schema and data exports.
  2. Inventory schemas, types, relationships, indexes, logic, users, permissions, replication, queries, jobs, and integrations.
  3. Record counts, checksums, aggregates, sizes, sequences, lag, performance, and recovery baselines.
  4. Hash all immutable backup and migration artifacts.

Proof to capture: A signed manifest reconciles every scoped record class, runtime dependency, export file, count, and hash.

Transformation · Schema migration files and ETL specification

Target schema and transformation registry

Define every structural, type, relationship, and logic decision.

  1. Inventory source values and exceptions.
  2. Define explicit destination mappings.
  3. Reject unmapped critical records.

Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.

Transformation · Native backup tools, pgloader or ETL, CDC, and verification SQL

Repeatable copy and change-capture pipeline

Load, catch up, verify, and cut over deterministically.

  1. Normalize encoding, dates, identifiers, and blanks.
  2. Run a representative pilot.
  3. Reconcile accepted, rejected, and transformed rows.

Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.

05Handle with care

The things most likely to hurt.

These are operating limits. Treat every “Stop if” condition as a blocked migration, not a suggestion.

Transform

Silent type coercion corrupts data

criticalpossible likelihood

Precision, timezones, encodings, booleans, nested values, or nulls change without a load error.

Consequence
Applications make incorrect decisions.
Mitigation
Use type fixtures, checksums, aggregates, and invariant queries.

Stop if: Any critical invariant or precision check fails.

Cutover

Final delta misses writes

criticalpossible likelihood

Change capture lags, drops unsupported operations, or stops before writers freeze.

Consequence
Source and destination diverge permanently.
Mitigation
Monitor lag and reconcile a final consistency point.

Stop if: Lag is nonzero or an unexplained delta exists.

Performance

Queries pass functionally but fail under load

criticalpossible likelihood

Indexes and planners differ from the source.

Consequence
Cutover causes timeouts or lock contention.
Mitigation
Benchmark production-shaped queries and concurrency.

Stop if: Critical latency, error, or lock thresholds are exceeded.

06Precise timeline

Do the work in this order.

Estimate forUp to 500 tables, 1 TB of data, 200 critical queries, and a 30-minute write-freeze objective
Total elapsed25–60 business days
Active work130–260 hours
BufferAdd time for stored procedures, triggers, spatial data, large objects, minimal downtime, heavy write load, or undocumented SQL behavior.
01
Days 1–3Inventory and decisions2–3 days
02
Days 3–5Backup and reconcile1–3 days
03
Days 5–12Map and pilot3–8 days
04
Days 10–20Final delta and switch1–5 days
05
Days 12–40Observe and close3–10 days
  1. Days 1–3 · inventory

    Inventory and decisions

    6–12 hours active2–3 days elapsedOwner review waiting
    • Inventory MySQL data, features, users, domains, and integrations.
    • Approve scope, owners, mappings, and exclusions.

    Depends on: MySQL and PostgreSQL administrator access

    Stop / go checkpoint

    Export?

    Go when: Every critical item has an owner and disposition.

    Stop when: Consent, billing, access, or system ownership is unclear.

  2. Days 3–5 · backup

    Backup and reconcile

    5–10 hours active1–3 days elapsedExport processing waiting
    • Create immutable exports and configuration evidence.
    • Reconcile counts, totals, and hashes.

    Depends on: Approved inventory

    Stop / go checkpoint

    Transform?

    Go when: Source totals and export manifests agree.

    Stop when: Any critical dataset or configuration is absent.

  3. Days 5–12 · pilot

    Map and pilot

    10–35 hours active3–8 days elapsedDestination processing and review waiting
    • Configure PostgreSQL and transform representative data.
    • Run a pilot containing normal records and every critical edge case.

    Depends on: Verified backup

    Stop / go checkpoint

    Scale?

    Go when: Pilot mappings, behavior, access, and evidence pass.

    Stop when: Any critical check fails or produces unexplained variance.

  4. Days 10–20 · cutover

    Final delta and switch

    5–25 hours active1–5 days elapsedDNS, import, or sync propagation waiting
    • Freeze production writes in MySQL.
    • Apply the final delta, switch ownership, and run blocking checks.

    Depends on: Passed pilot and approved rollback

    Stop / go checkpoint

    Open production?

    Go when: Counts reconcile and one destination system owns production.

    Stop when: A source writer remains active or a blocking check fails.

  5. Days 12–40 · observe

    Observe and close

    3–18 hours active3–10 days elapsedOperating-cycle evidence waiting
    • Monitor one complete operating cycle.
    • Sign the verification report and close rollback only after stability.

    Depends on: Verified cutover

    Stop / go checkpoint

    Close rollback?

    Go when: No trigger occurs during the agreed observation period.

    Stop when: Data, access, delivery, routing, or business results regress.

07The point of change

Cut over with a way back.

Go live

Cutover

Make PostgreSQL the only production system without losing the final MySQL delta.

Recommended window: A low-volume weekday morning with platform, data, DNS, and business owners available.

  1. Freeze production writes and scheduled actions in MySQL.
  2. Export, transform, and reconcile the final delta.
  3. Apply the approved delta to PostgreSQL.
  4. Switch domains, forms, integrations, sending, or sync ownership as applicable.
  5. Run every blocking verification check and keep the source intact.

Proof to capture: PostgreSQL owns production, totals reconcile, and every blocking check has durable evidence.

Return to safety

Rollback

Return production ownership to MySQL without losing destination-era changes.

Deadline: Within seven days and before source data, plans, credentials, domains, or billing are changed.

  1. Stop new writes and scheduled actions in PostgreSQL.
  2. Restore the prior MySQL routing, forms, integrations, sending, or sync ownership.
  3. Export the PostgreSQL post-cutover delta.
  4. Review and apply safe destination-era changes to MySQL.
  5. Run the same blocking checks against the restored source.

Proof to capture: MySQL again owns production with current data and no duplicate destination action.

Rollback immediately when
  • Unexplained critical count or value variance
  • Missing or exposed critical data
  • Duplicate production action
  • Failed access, routing, delivery, or integration check
  • A critical feature has no safe destination replacement
08Verification report

Prove the migration worked.

Every blocking check must pass. Capture the evidence before cleanup begins.

0%
Interactive report preview0 / 8 checks passed
PassIDCheckMethodExpected resultEvidence
V-01BlockingRecord reconciliationCompare counts, checksums, aggregates, and stratified records.Every scoped record is accounted for.Data ledger.
V-02BlockingValue fidelityRun type fixtures covering bounds, nulls, precision, Unicode, and timezones.No silent coercion or truncation.Type report.
V-03BlockingReference and constraint integrityQuery parents, children, orphans, duplicates, and cascades.Every critical invariant holds.Integrity report.
V-04BlockingViews, formulas, triggers, and proceduresRun approved input and failure cases.Outputs and side effects match acceptance.Logic suite.
V-05BlockingFunctional and performance parityRun production-shaped reads and writes under concurrency.Results and service objectives pass.Benchmark report.
V-06BlockingRoles and data accessRun allowed and denied operations for every role.Least privilege matches policy.Access evidence.
V-07BlockingBackup, restore, and rollbackRestore a destination backup and execute the rollback rehearsal.Recovery objectives and integrity pass.Recovery report.
V-08BlockingReplication and write authorityInspect lag, writers, jobs, and application connections.PostgreSQL alone accepts approved writes with zero unexplained delta.Cutover checklist.
09Post-migration cleanup

Remove the scaffolding safely.

Safe after: One complete operating cycle, at least seven stable days, and owner sign-off on every blocking check.

  1. Create final MySQL exports and archive verification evidence.
  2. Revoke temporary credentials, API keys, webhooks, and elevated roles.
  3. Remove obsolete embeds, forms, jobs, integrations, and DNS records.
  4. Keep the source intact through the approved retention window.
  5. Cancel paid plans only after billing, legal, and recovery review.
  6. Schedule the next PostgreSQL backup, access, and migration-playbook review.
Sources and maintenance

Built to be reviewed.

Tested 2026-07-19. Next scheduled review: 2026-10-19.

  1. PostgreSQL wiki: proper MySQL migrationAccessed 2026-07-19
  2. pgloader: MySQL to PostgreSQLAccessed 2026-07-19
  3. MySQL: mysqldump referenceAccessed 2026-07-19