Migration · 2026-05-04 · By RedDB team · 9 min read
When NOT to migrate: a checklist
The companion piece to every migration post. A decision tree for staying on your current stack — team size, pain quantification, runway — so you do not pay migration tax for a problem you did not have.
Most migration posts are sales pitches dressed up as advice. This one is the opposite. We have helped four teams migrate off Firebase and three off MongoDB in the last twelve months, and the most useful conversation we have with prospective customers is the one where we tell them not to migrate yet.
A migration is a project that has a real shape: weeks of senior-engineer time, an integration risk window, a regression bug or two that ships to production, and a quarter of feature work you did not do because you were busy moving data. If the pain you are fleeing is smaller than that, you are about to trade a known annoyance for an unknown one. So before you cut, run the checks below. Each one ends in a “stay” verdict if the answer is honest. We have written it as a checklist on purpose — if you can put a tick next to every “stay” signal, close this tab and go back to the feature you were building.
Check 1: have you actually quantified the pain?
Engineers migrate because something feels slow, expensive, or fragile. “Feels” is not a metric. Before you spend a quarter on a migration, the following numbers should be on a shared doc:
- The actual dollar cost per month, broken out by line item. Not “Firebase is expensive” — “Firestore reads are $4,800/mo and growing 18% MoM.”
- The actual P99 latency of the queries that hurt. Not “Mongo is slow” — “the
$lookuppipeline behind /feed runs in 1.4s P99 and we have a 300ms target.” - The actual incident count attributable to the current stack in the last 90 days. Not “we have ops pain” — “three Sev-2s in 90 days, two of which were rooted in MongoDB primary failover behaviour.”
If you cannot put numbers in those three slots, your pain is vibes. Stay. Spend the next two weeks instrumenting instead. Half the time the numbers come back smaller than the team’s intuition, and the migration cancels itself.
Check 2: how big is the team?
Migrations have a U-shaped cost-by-team-size curve. The two-person team can move fast (no coordination tax) but cannot afford to lose either engineer for four weeks. The fifty-person team has the slack but pays an enormous coordination cost (every team owns part of the schema). The teams that suffer least are in the awkward middle — five to fifteen engineers — and that is also where most of our customers sit.
| Team size | Migration mode that works | What to watch out for |
|---|---|---|
| 1–2 engineers | Cut over in a sprint, no dual-write phase | One bad incident kills the company. Have a rollback plan you have actually tested |
| 3–5 engineers | Dual-write for two weeks, then promote | The engineer doing the migration cannot also be on-call. Pre-negotiate this with the team |
| 6–15 engineers | Dual-write for a month, feature-flag the read side | The migration owner needs explicit air cover from the CTO. Otherwise feature work eats the schedule |
| 16+ engineers | Per-service migration over a quarter | Every service owner thinks their slice is special. Budget time for the meetings |
Stay if your team is at the edges (1 or 16+) and the pain numbers from Check 1 are not severe. The smallest teams should stretch the existing stack until either revenue or a hire makes a migration safer; the largest teams should plan a per-service migration as a multi-quarter program, not a project.
Check 3: is the pain in the data layer or somewhere else?
This is the check we wish more teams ran first. “The database is slow” turns out, surprisingly often, to be “our N+1 query in the orders service is slow” or “the cache layer is bypassed for the homepage.” Run an honest five-day investigation before you blame the storage engine:
- Profile the worst three endpoints. Where is the latency actually accumulating?
- Look at the query plans for the worst three queries. Are they doing what you expect?
- Check whether the most expensive endpoints have working caches and whether the caches are actually hit.
- Audit the slow-query log for the last week. Are 80% of the slow queries from a handful of identifiable shapes?
If the answer is “yes, it is a small number of fixable shapes” — stay. A query rewrite is cheaper than a migration, even when the migration eventually arrives anyway. We have watched teams migrate to “fix” a Mongo problem that turned out to be an unindexed field; they shipped the same N+1 query on the new engine, and the new engine ran it slowly too.
Check 4: what is your runway?
Migrations consume runway. Concretely:
- Senior-engineer-weeks: figure 4–10 depending on dual-write scope.
- Reduced feature velocity for the rest of the team during the cutover window (people get pulled into adjacent reviews and incident response).
- A higher-than-baseline rate of regressions in the first 30 days after cutover.
If your company will run out of money inside that window, stay. If the pain from Check 1 is “we’ll be insolvent if Firestore bills keep growing,” consider a partial migration — move only the worst-cost path to a cheaper store, do not rewrite the auth path or the document model. Partial migrations sound ugly on the architecture diagram and work fine in practice.
Check 5: do you have a tested rollback?
Every migration plan promises rollback. Roughly one in four actually has one that has been exercised. Before you start, write the runbook for “the new engine is on fire, we need to be back on the old one in two hours.” Read it back to yourself. Can you actually do it?
The honest version of rollback looks like:
- Dual-write was on the whole time, so the old store still has correct data through last write.
- Feature flag flips reads back to the old store.
- Whatever writes happened only on the new store between cutover and rollback are surfaced for manual reconciliation (a script lists them; a human reviews).
- The team has actually run this end-to-end on staging within the last two weeks.
If steps 1–4 are not all true, stay. Tighten the rollback story until they are. The cost of doing this work is much smaller than the cost of an unplanned rollback at 3am, and roughly the same as the cost of an unplanned non-rollback (the case where rollback was possible in principle but nobody dared push the button).
Check 6: is the new stack actually better for your shape?
This is where we will be most direct against our own product. RedDB is good at workloads with cross-shape access patterns (RAG over mutable docs, agent memory, search-over-application-data, multi-tenant SaaS where you need vector + text + structured per tenant). It is not the right choice for:
- Single-shape workloads. If you only need OLTP, Postgres is more mature and has a larger labour market. Stay on Postgres.
- Analytics-dominant workloads. If 80% of your queries are scans over historical data, ClickHouse or DuckDB will beat us. Stay on what you have until you can move to a column store.
- Embedded / single-process workloads. SQLite is the right answer for a desktop app or a CLI. We are an over-investment.
- Hyper-low write volume. If your bill on the current managed Postgres is $40/mo, the operational overhead of a less-mature engine is the bigger cost. Stay on the managed service.
We wrote a whole post on this — When you don’t need RedDB — and the short version is: if the migration target is not unambiguously better for your specific workload shape, the migration is paying for an answer to a question you did not ask.
Check 7: who on the team will own the new stack at 3am?
This is the social check, and it kills more migrations than any technical one. Migrations frequently succeed for six months and then quietly fail in month nine when the engineer who ran the migration leaves the company. The new stack is now an artifact nobody understands; on-call rotations get awkward; the next migration is back to the old engine.
Before you migrate, name on a shared doc:
- The primary owner of the new stack.
- The secondary owner.
- The cross-training plan to get to at least three people who can debug it under pressure.
- The runbook location.
- The dashboards.
If you cannot fill in those slots with real names, stay. Hire or train first.
The “go” signal looks like this
After all seven checks, you should migrate only if all of these are true:
- The pain has real numbers attached, and the numbers are worse than the migration cost.
- The team size matches a viable migration mode (or you can wait until it does).
- The pain is genuinely in the data layer, not somewhere upstream.
- The runway covers the migration window with a buffer.
- A rollback plan exists and has been exercised on staging.
- The new stack is unambiguously better for your specific workload shape.
- At least two engineers will own the new stack with names on a doc.
If even one of those is false, the cheapest move is “stay, fix the highest-leverage thing on the current stack, revisit in a quarter.” We tell prospective customers this often enough that we have a stock phrase for it: the best migration is the one you did not have to do this quarter.
TL;DR
Migrations look like architecture work and behave like organisational work. The technical part is comparatively easy; the runway, ownership, and rollback parts are what kill projects. Before you cut over, write down the numbers (Check 1), match the team size to a viable mode (Check 2), make sure the pain is actually in the data layer (Check 3), confirm runway (Check 4), exercise rollback (Check 5), check the new stack fits your shape (Check 6), and name the people who will own it (Check 7).
If you tick every box, run the migration. If not, the Out of Firebase and Mongo → RedDB posts will still be here in six months when the answer is yes.
In the meantime: instrument, profile, rewrite the worst queries, fix the cache, and bank the engineer-weeks. That is the boring answer and it is right more often than the exciting one.
RedDB Cloud
Join the private beta.
One-click managed deploy. Free during beta. Founding pricing locked at GA.
Request access →