Post
MongoDB Atlas to PlanetScale Postgres: how we migrated 4 million documents in a day
We migrated our production investor-relations platform from MongoDB Atlas to PlanetScale Postgres in one day — zero data loss, a production database bill cut...
Commentary
We migrated our production investor-relations platform from MongoDB Atlas to PlanetScale Postgres in one day — zero data loss, a production database bill cut 5× ($5,749 to $1,149 a month), and our hottest page query dropped from ~530 ms to under 9 ms, server-side to server-side. This is the engineering story: the mirror-schema design, the fail-loud translation layer, the verification gates, and the two things that bit us anyway. 6ix.com is an investor-relations platform: public companies host live investor events — video, registration, real-time chat — and investors use 6ix to research and follow thousands of public companies. Behind it sits a Node/Express monolith that talked to MongoDB Atlas through Mongoose — 69 collections, about 4 million documents, 54 GB. On July 2nd we cut production over to a single PlanetScale Postgres cluster (M-320 Metal: 4 vCPU, 32 GB RAM, NVMe, one primary + two replicas). The whole engagement — from "get the repo running" to "Mongo is frozen and the mongoose dependency is deleted" — took about a day of wall-clock time, executed by a fleet of AI agents (Claude's Fable 5) with a human making the calls. This post is about the engineering that made that safe. Why we moved Three reasons, in honest order: Cost. The production database's final full Atlas invoice (June 2026) was $5,749 pre-tax — $6,821 at the org level once tax and sibling projects are included — for a workload that, measured honestly, runs at 28 transactions per second with a 99.9% read ratio. The PlanetScale cluster that replaced it is $1,149/month on the same pre-tax basis: exactly 5× less — and after migration it runs at a 99.94% buffer-cache hit rate with the entire working set in RAM. Speed. Our worst production queries were aggregation pipelines Mongo executed in hundreds of milliseconds. We benchmarked the same data on both systems before committing (numbers below). One less query language. Every new feature was paying the "how do I express this in an aggregation pipeline" tax. SQL with jsonb is a better fit for how the product queries its data. The core design decision: a verbatim mirror schema The riskiest way to do a MongoDB-to-Postgres migration is to redesi...