The month I migrated off Firebase at $26K MRR: a founder diary (2026)
The month I crossed $26K MRR, my Firebase bill jumped almost six times with no new growth. A composite founder diary on Firestore read costs, migrating the hot paths to Postgres, and why the pattern, not the tool, was the real problem.
Updated on July 23, 2026

In this story
“The invoice was $2,300. We had not grown that month. One screen was just reading the entire database every single time somebody opened it.”
By the numbers, the month I crossed $26K MRR looked like every other good month. Revenue up a little, churn flat, roughly 600 paying customers on a small B2B SaaS I run alone. Then the infrastructure bill landed, and it was almost six times what it had been in the spring. Nothing in the product had changed. What had changed was that I finally had enough traffic for a lazy data-access pattern to start printing money in the wrong direction.
Quick answer (2026): At about $26K MRR my
Firebase (Cloud Firestore) bill jumped from roughly $400 a month to about $2,300 in a single billing cycle. The cause was not growth. It was read volume: one analytics screen re-read a whole collection on every load, and a couple of real-time listeners sat on a busy page. Firestore bills per document read, write, and delete, so a chatty read pattern scales your invoice faster than your revenue. I spent about six weeks migrating the hot paths to
Postgres, dropped steady-state infra to around $300 a month, and nearly broke the app twice on the way. The real lesson: I was not migrating off a bad tool, I was migrating off a bad pattern. Fix the pattern first, then decide if you still need to move.
This is a composite founder diary. The company, segment, and exact dates are anonymized, and every dollar figure is self-reported and rounded to protect privacy. Details are merged from more than one operator I know, including me, so nobody is identifiable. The Firestore billing mechanics and free-tier limits below are real and linked to Firebase's own 2026 pricing. Nothing here is a real named person's verbatim quote.
The bill that did not match the growth
I remember refreshing the billing page twice because I assumed it was a display bug. $2,300 for a month where I had added maybe forty net new customers. My mental model of the product was "cheap to run." That model was two years old and had quietly stopped being true.
The first mistake was emotional, not technical. My gut said "Firebase is ripping me off, I need to leave today." That is the exact wrong headspace to make an architecture decision in. Panic migrations are how you turn a cost problem into an outage problem. So before I touched anything, I made myself do the boring thing: figure out where the money was actually going.
Why Firestore gets expensive quietly
Cloud Firestore does not bill by how much data you store, mostly. It bills by how many times you touch it. Every document read, write, and delete is a metered operation, on top of stored data and network egress (Firebase pricing, 2026). The free Spark tier gives you 50,000 reads, 20,000 writes, and 20,000 deletes per day, and above that you are on metered pay-as-you-go pricing.
That model is genuinely great when you are small. It is why I chose it. At launch I was doing a few thousand reads a day and paying nothing. The trap is that reads are invisible in your code. A getDocs on a collection that has grown to 8,000 rows is one line that looks identical whether it returns three documents or eight thousand. Multiply that by a dashboard that fires it on every page load, times a few hundred customers checking their numbers every morning, and you have manufactured millions of reads a month without writing a single new feature.
When I finally added per-operation logging, the picture was embarrassingly clear. One analytics screen was responsible for about 70 percent of my reads. It re-fetched an entire collection client-side to compute a chart that could have been a single aggregated query. Two real-time listeners on a busy settings page accounted for most of the rest, re-reading documents every time anything in the collection changed.
The math I should have run a year earlier
Here is the arithmetic I wish I had done at $10K MRR instead of $26K MRR. Cost per customer per month on infrastructure had crept from a couple of cents to nearly four dollars. On plans averaging around forty dollars, that is a tenth of my gross margin going to reads that mostly recomputed the same numbers. It was not going to bankrupt me. But it was a line that grew with usage, not with revenue, which meant my best customers, the ones who logged in daily, were also my most expensive to serve. That is a quietly dangerous shape for a business.
I had felt a version of this fear before, the month I watched my runway math get thin and wrote about it in the month I almost ran out of cash at $17K MRR. Cash panic teaches you to look at the trend line, not the single number. A $2,300 bill is survivable. A $2,300 bill that is $4,000 in six months at the same growth rate is a strategy problem.
The decision: migrate the pattern, not just the data
The move that saved me was reframing the project. I was not "leaving Firebase." I was moving the three or four hottest read paths onto a database whose cost did not scale with how often I looked at the data. Postgres bills you for a server that runs whether you query it once or a million times, which is exactly the opposite pressure. For read-heavy dashboards, that flat pressure is what you want.
I kept auth and a couple of genuinely real-time features on Firebase for the first phase. This is the part I would underline for anyone considering the same move: you almost never need a big-bang migration. I ran both systems in parallel, dual-writing to Postgres while still reading from Firestore, until I trusted the new tables. Teams far larger than me have documented this same incremental, strangler-style approach rather than a single cutover (Traba Engineering, "Out of the Firestore," 2024).
Two weeks that nearly broke me
I will not pretend it was smooth. Two moments still make my stomach drop.
The first was a backfill bug. My script that copied historical documents into Postgres silently skipped about forty records because of a null field my schema did not allow. I only caught it because I had written a dumb little reconciliation check that counted rows on both sides every night. If I had trusted the migration and skipped that check, I would have quietly lost data and found out from a customer.
The second was worse and it was about authorization. In Firestore, a lot of my access control lived in Security Rules, not in my application code. Moving to Postgres meant rebuilding all of that authorization logic in the app layer, and I missed one check. For about an hour in staging, one tenant's list was queryable by another tenant. It never touched production, but it was a cold reminder that Security Rules had been doing real work I had stopped thinking about. If you move off Firebase, inventory every authorization decision its rules were quietly making for you before you flip anything.
That fortnight also ate every other job. Support, sales, the roadmap, all of it stalled while I was elbow-deep in migration scripts, the same tunnel-vision failure I described in the month support tickets ate my week at $25K MRR. Being solo means a two-week deep project is also a two-week outage on everything else you do. Budget for that, because it is the real cost nobody puts on the invoice.
What it actually cost, and what it saved
Six weeks of nights and weekends. One near-miss on data, one near-miss on tenant isolation, and a lot of coffee. Steady-state infrastructure went from about $2,300 at the peak to roughly $300 a month on a managed Postgres box plus what stayed on Firebase. Published case studies land in the same neighborhood, with teams reporting cost reductions on the order of 80 percent after moving read-heavy workloads to Postgres. My gross margin got its ten points back, and more importantly the cost line stopped growing every time a customer logged in.
But I want to be honest about the counterfactual, because this is where most migration stories lie by omission. If I had simply replaced that full-collection read with one aggregated query and put a short cache in front of it, I could have cut the bill by more than half without migrating anything. Firebase was never the villain. My read pattern was. The migration was worth it for the flat cost curve and for owning my data model in plain SQL, but a founder with less time could have gotten 60 percent of the benefit in an afternoon by fixing the pattern in place.
The one thing I would tell past me
If I could send one message back to the version of me shipping this app at $3K MRR, it would be this. Put a number on the cost of your three most-loaded screens before you have to.
- Add per-operation cost logging early, while it is cheap and nobody is yelling. You cannot fix a bill you cannot see broken down by feature.
- Treat "reads that scale with logins, not with revenue" as a code smell, not an accounting detail. Cache aggressively, aggregate on the server, and never re-read a whole collection to draw one chart.
- When you do migrate, do it incrementally with dual writes and a reconciliation check, and inventory every authorization rule before you move it. Big-bang cutovers are how migrations become incidents.
The bill scared me into a good decision, but the decision I actually needed was smaller than the one I made. Measure cost per feature before the invoice measures it for you. At $26K MRR, solo, that one habit is the difference between infrastructure that fades into the background and infrastructure that slowly eats your margin while you are busy calling it growth.
Sources
- Firebase, "Firebase Pricing" (Cloud Firestore billing model and Spark free-tier limits), 2026. https://firebase.google.com/pricing
- Traba Engineering, "Out of the Fire(store): Traba's Journey to Postgres," 2024. https://engineering.traba.work/firestore-postgres-migration
Written by
Anya PetrovaAnya Petrova writes first-person founder diaries for OperatorBook, tracing the messy operational reality behind each MRR milestone.
Frequently asked questions
Why did my Firebase bill spike without adding users?
Cloud Firestore bills per document read, write, and delete, not by how much data you store. A single screen that re-reads a whole collection on every load, or real-time listeners on a busy page, can generate millions of reads a month with no new features. In this 2026 diary the bill went from about $400 to $2,300 purely from read volume at roughly 600 customers and $26K MRR.
How does Cloud Firestore pricing actually work in 2026?
Firestore charges for document reads, writes, deletes, stored data, and network egress. The free Spark tier includes 50,000 reads, 20,000 writes, and 20,000 deletes per day; beyond that you pay metered pay-as-you-go rates (Firebase pricing, 2026). Because reads are metered, read-heavy dashboards tend to drive most of the cost.
Should I migrate off Firebase to Postgres to save money?
Not automatically. First check whether your cost is a pattern problem. Often a full-collection read replaced by one aggregated query plus a short cache cuts the bill in half with no migration. Migrate when you want a flat cost curve that does not scale with logins and you want to own your data model in SQL. In this composite case, moving the hot read paths took steady-state infra from about $2,300 to about $300 a month.
How long does a Firebase to Postgres migration take for a solo founder?
In this diary it took about six weeks of nights and weekends for a small app, moving only the hottest read paths first. Larger teams have documented multi-month incremental migrations. Budget for the hidden cost too: a solo two-week deep migration is also a two-week stall on support, sales, and roadmap.
What is the most dangerous part of leaving Firebase?
Authorization. In Firestore a lot of access control lives in Security Rules, not application code. Moving to Postgres means rebuilding that logic in your app, and it is easy to miss a check and expose one tenant's data to another. Inventory every authorization decision your Security Rules were making before you move anything, and run a nightly row-count reconciliation to catch silent data loss during backfill.
What is the single biggest lesson from this migration?
Measure cost per feature before the invoice measures it for you. Add per-operation logging early, treat reads that scale with logins rather than revenue as a code smell, and migrate incrementally with dual writes. The bill was a bad-pattern problem, not a bad-tool problem.
More stories
The month support tickets ate my week at $25K MRR: a founder diary (2026)
By the numbers it was my best month ever. By the way it felt, it was the month the job stopped being building and started being answering. A support-overwhelm diary at $25K MRR.
The month I killed the feature everyone asked for at $14K MRR: a founder diary (2026)
Everyone asked for it. Almost nobody used it. The month I reached $14K MRR, I killed the most-requested feature on my roadmap and learned the difference between what customers ask for and what they actually use.


