Back to journal

Engineering · 9 min read

What Firebase Gives You (And What It Quietly Costs)

Firebase is not magic. It's a very good collection of products that work well together and have real tradeoffs. Understanding those tradeoffs — before you're stuck with them — is the whole game.

The Integrated Stack Advantage

Firebase's real value proposition isn't any individual product. Firestore is good but there are comparable databases. Cloud Functions is useful but AWS Lambda and similar alternatives exist. Firebase Auth is convenient but you can implement authentication without it. What Firebase offers that's genuinely hard to replicate without significant effort is the integration between all of these things, working coherently, with consistent SDK patterns, under one authentication model, with unified logging and monitoring.

For a small team — or a solo developer who needs to move quickly without becoming an infrastructure engineer — this integration is enormously valuable. The time you don't spend on wiring up auth to talk to your database, setting up service accounts for Cloud Functions to access Firestore, configuring CORS for storage uploads, debugging why your monitoring doesn't capture data from one particular service — that time is real. For Twunein, the Firebase stack means I can focus on the product problems rather than the infrastructure plumbing. That's a genuine and significant advantage.

Firestore is the right fit for Twunein's current architecture: session state, member presence, and queue updates all live in documents and subcollections so the app can stay fully Firestore-backed. Firestore is excellent for documents and queries, and with a session document plus subcollections it covers the product's real-time needs without requiring a second database.

The Cold Truth About Vendor Lock-In

Using Firebase extensively means being locked in to Firebase extensively. This is not a secret or a hidden cost — Google makes no bones about it — but it's easy to underestimate how deep the lock-in goes before you've experienced it.

The lock-in isn't just in the data model. It's in the security rules language, which is Firebase-specific and not transferable. It's in the Cloud Functions execution environment, which has Firebase-specific features that don't exist in generic serverless platforms. It's in the client SDKs, which abstract away the API in ways that make it non-trivial to swap out the underlying service without rewriting substantial client code. It's in the pricing model, where your cost projections depend on Firebase's specific pricing structure and change when that structure changes.

I want to be honest about my own position: I'm locked in to Firebase for Twunein, Drimin, and Trenziq. I've evaluated this and concluded that the tradeoff is worth it for the current scale and team size. If I need to migrate at some point — because pricing becomes untenable, because a feature I need doesn't exist in Firebase, because Google changes something fundamental — that migration will be expensive. I know this. I've accepted it because the alternative is spending time on infrastructure rather than product, which is the wrong tradeoff for where these apps are right now.

What I'd counsel: go in with eyes open. Firebase lock-in is real. The question isn't whether it exists but whether the benefits justify accepting it for your specific situation.

Cost at Scale: The Honest Version

Firebase's free tier (Spark) is genuinely useful for development and for small apps. The paid tier (Blaze, pay-as-you-go) scales with usage in ways that are sometimes surprising to developers who haven't done the maths in advance.

Firestore costs per read, write, and delete operation. Cloud Functions costs per invocation and per compute-second. Storage costs per GB stored and per GB transferred. These individual costs are small enough to be invisible at low scale. They become visible at mid-scale and significant at high scale. The specific operations that are expensive are sometimes non-obvious — a query that returns 1000 documents costs 1000 reads, not 1 query. A Cloud Function that's invoked frequently for a high-traffic feature can accumulate meaningful compute costs.

I've built cost alerts, I've profiled the read/write patterns in the apps, I've optimised the queries that were unnecessarily expensive. This is normal and expected Firebase development practice. But it's work that needs to happen proactively rather than reactively. The bill that arrives unexpectedly because a query was inefficient at scale is a real risk, not a hypothetical one.

For Twunein's current scale, Firebase costs are manageable. For an app that reached significantly higher user volumes without a corresponding revenue model, the cost conversation would be different. Planning for that conversation in advance — understanding which operations are most costly and which traffic patterns would produce the biggest cost increases — is part of responsible Firebase adoption.

The Security Rules Learning Curve

Firestore and Storage security rules are one of Firebase's genuine friction points. The rules language is declarative and powerful, but it's also deeply unintuitive until you've spent real time with it. The mental model for rules — particularly for rules that need to check data in other documents, or that need to validate complex conditions — is different from most access control systems.

The most common mistake is rules that are subtly too permissive in ways that aren't immediately obvious. A rule that checks whether the requesting user is a participant in a session sounds correct until you realise that the field it's checking against is writeable by the client, so a malicious client can write themselves into any session. The rules language provides the tools to write correct, secure rules. It also requires understanding the data model well enough to anticipate these attack vectors.

I use the Firebase emulator suite and the rules unit testing library to validate rules before deploying them. This is essential. Testing rules in production by checking whether things work as expected is insufficient — you need to actively try to break them. The emulator environment makes this practical without risk.

Why It's Still Right for Twunein Right Now

Given all of the above — lock-in, cost, rules learning curve — Firebase remains the right choice for Twunein at its current stage. The reasoning: the integrated stack lets a small team move at a pace that wouldn't be possible with a more modular infrastructure. The real-time capabilities are a genuine fit for the product's core requirements. The India region infrastructure supports the performance requirements for an Indian user base. The FlutterFire integration is mature and reliable.

Critically, the problems that Firebase creates — lock-in, cost uncertainty, rules complexity — are problems I can manage. The problems it solves — infrastructure time, auth complexity, real-time sync infrastructure — are problems that would be significantly more expensive to solve without it. The tradeoff is real but it goes in the right direction for where the product is now.

The question of when this might change: if the user base grew significantly, the cost model would need re-evaluation. If a major feature requirement emerged that Firebase's data model genuinely doesn't support well, that would trigger a reassessment. If Google made significant pricing or service changes, as they have done to other GCP products before, that would force a conversation about migration. None of these are happening now. All of them are worth having a contingency plan for.

When to Reconsider

Firebase is not the right answer for every app and every team. It's not right when you need complex relational queries — Firestore's query model is document-oriented and there are real limitations to what you can express without significant data duplication or denormalisation. It's not right when data sovereignty requirements mandate infrastructure you own and control. It's not right when your cost model depends on predictable, flat-rate infrastructure rather than pay-per-operation pricing. It's not right when your team has strong backend engineering capacity and the integrated convenience of Firebase offers less relative value than a more flexible self-managed stack.

The right time to reconsider is before you've built deeply on it, which is admittedly difficult to arrange in practice. The second-best time is when a specific limitation becomes a genuine blocker, at which point you'll have a concrete case for the migration investment. The wrong time to reconsider is in a reactive, crisis-driven way because a bill was unexpectedly high or a feature turned out to be genuinely impossible. That kind of reactive re-evaluation is expensive and stressful. Build the monitoring and cost alerts early enough that you see problems coming rather than arriving as surprises.

Listen together, wherever you are.

Twunein keeps both of you in the same second of the same song.

Our Network