What Firebase is, and what it assumes
Firebase is Google's app-development platform: a database (Firestore), authentication, file storage, hosting, and more. It is mature, well-documented, and trusted at enormous scale. For real-time and offline-first mobile apps in particular, it is still hard to beat.
But Firebase was designed in a different era of app building, and it carries two assumptions that quietly cost a non-technical builder. The first is that a document model is what you want. The second is that you will write rules to keep data safe. Both deserve a closer look.
Document vs. relational — why it matters
Firestore stores data as documents — JSON-like objects grouped into collections, with no fixed schema. That flexibility is pitched as a feature, and for some shapes of data it is. But most apps a builder actually ships are relational: a user has orders, an order has items, a post has comments. In a document store, those relationships are something you stitch together in application code, and queries that span them are constrained.
Schema-less also means nothing keeps your documents consistent. If your code saves price as a number in one place and a string in another, Firestore stores both without complaint — and the bug surfaces later, in production. A relational database like PostgreSQL keeps a column one type. Cradler gives you that consistency without making you define the columns: it infers the type from your first value and holds the line after that.
Security Rules vs. dashboard toggles
Firestore data is not safe until you say so. Access is governed by Security Rules— logic written in Firebase's own rules language that runs on every read and write. They are powerful and they are also a genuine source of bugs: too loose and your data is exposed, too tight and your own app breaks. For a non-technical builder, the rules language is one more thing to learn that has nothing to do with the app they wanted to make.
Cradler's model is deliberately small. Every table is closed by default. For each one you check boxes — may the public anon key read, insert, update, delete? — and the service key, used only in server code, bypasses them. There is no rules language, and the safe state is the default, not something you have to remember to configure.
Cradler vs. Firebase, point by point
Database model
Firebase
Firestore is a NoSQL document store — collections of JSON-like documents, no fixed schema, limited joins.
Cradler
Managed PostgreSQL — a real relational database with rows, columns, and standard queries.
Securing the data
Firebase
Firestore Security Rules, written in Firebase's own rules language, gate every read and write.
Cradler
Tables are deny-by-default. You toggle read/insert/update/delete per table in the dashboard.
Schema
Firebase
Schema-less by design — flexible, but it is on you and your code to keep document shapes consistent.
Cradler
The schema auto-evolves and stays consistent: a new field becomes a real column, typed from its value.
Cost model
Firebase
The Blaze plan bills per document read, write, and delete — costs scale with how your queries are shaped.
Cradler
First month free, then one predictable bill for the database, file storage, and usage together.
Portability
Firebase
Client code and rules are tied to Firestore's semantics, so moving off it later is real work.
Cradler
Standard PostgreSQL underneath — your data is exportable and not locked to Cradler.
The cost question
Firebase's Blaze plan bills Firestore by the operation: you pay per document read, per write, and per delete. That ties your bill to the shape of your queries in a way that is hard to predict — a screen that reads a long list reads many documents, and the cost follows. Builders are regularly surprised by it.
Cradler's billing does not depend on how you wrote a query. The first month is free with no credit card, and after that one bill covers the database, file storage, and usage together — no separate line for storage or bandwidth, and no per-document meter. Current numbers are on the pricing page.
What a read looks like
Querying in Firestore means composing collection references and often pre-building composite indexes for anything beyond a simple filter. The same query in Cradler is a typed chain, and the database handles indexing:
import { createClient } from "@cradler/sdk";
const cradler = createClient({
url: process.env.NEXT_PUBLIC_CRADLER_URL!,
projectId: process.env.NEXT_PUBLIC_CRADLER_PROJECT_ID!,
apiKey: process.env.NEXT_PUBLIC_CRADLER_ANON_KEY!,
});
// Published posts by one author, newest first.
export async function postsByAuthor(authorId: string) {
const { rows } = await cradler
.from("posts")
.select("id", "title", "excerpt", "publishedAt")
.eq("authorId", authorId)
.eq("status", "published")
.order("publishedAt", { desc: true })
.limit(20);
return rows;
}
// One post, or null — no composite index to declare first.
export async function getPost(id: string) {
return cradler.from("posts").select().eq("id", id).first();
}When to choose Firebase instead
Firebase is a strong platform and there are honest reasons to stay with it:
- You are building an offline-first mobile app and want Firestore's local cache and automatic sync.
- You need live, real-time updates pushed to many clients today — a chat, a presence indicator, a collaborative view.
- You already use Google's ecosystem — Firebase Auth, Cloud Functions, Analytics — and want it all in one console.
- Your data really is document-shaped and largely self-contained.
Cradler's MVP is focused on a relational database and file storage; it does not do realtime sync today. If real-time or offline-first is central to your app, Firebase is the right call. If you mainly need to store and query relational data without learning a rules language or a document model, Cradler is the simpler fit.