When Not to Migrate from MySQL to PostgreSQL
I run PostgreSQL for a living and I still tell some teams to stay on MySQL. Here are the cases where migrating is the wrong call, and a decision framework that beats database dogma.
Notes for the problems that show up after launch: bad plans, awkward migrations, index debt, vacuum pressure, replica lag, and the small decisions that make PostgreSQL easier to operate.
I run PostgreSQL for a living and I still tell some teams to stay on MySQL. Here are the cases where migrating is the wrong call, and a decision framework that beats database dogma.
The parameter was nvarchar, the column was varchar, and four million rows got converted one at a time. How CONVERT_IMPLICIT turns seeks into scans, why ORMs cause it so reliably, and where to fix it for good.
Random UUIDs punish InnoDB's clustered index far harder than PostgreSQL's heap, but neither engine loves them. Here is the real damage model, and how UUIDv7 and ULID change the math.
An InnoDB FULLTEXT index is a family of hidden auxiliary tables with its own parser, stopwords, and deferred deletes. Where the edges are, which knobs demand a rebuild, and when to move search out of MySQL.
Logical backups scale badly by default. Field notes on where mysqldump stops working, what mydumper and myloader change, and the honest boundary where physical backups win.
Raising max_connections is the most common MySQL tuning move and usually the wrong one. Here is how thread-per-connection actually costs you, why Threads_running is the real signal, and how to size app pools and ProxySQL with actual math.
The planner picked a nested loop that ran 400,000 times because n_distinct was off by a factor of 30. Raising one column's statistics target fixed the estimate — and the plan — in a single ANALYZE.
MySQL memory is not just the buffer pool. This guide maps global versus per-session allocations, shows how to interrogate performance_schema memory instrumentation, and walks through a real OOM-kill postmortem workflow.
InnoDB hides old row versions in undo logs and reclaims space with rebuilds; PostgreSQL keeps dead tuples in the heap and reclaims them with VACUUM. Two different bloat models, two maintenance disciplines.
The nightly backup nobody restores is a rumor. A field guide to mariabackup: full and incremental chains, prepare discipline, encryption and Galera SST, the redo log-copy race, and the restore drill that proves it all.
The MySQL-to-MariaDB path is a logical migration, not an in-place upgrade. What breaks — auth plugins, JSON semantics, GTID, collations — and the checklist to run before you switch.
CTEs and window functions made MySQL 8.0 queries readable, and occasionally much slower. Field notes on derived_merge, materialization, window frame costs, and the cases where the old JOIN still wins.