Skip to content
    Field notes

    Firebase vs Supabase for Flutter: the trade-off nobody mentions

    Postgres versus Firestore is the argument everyone has. The one that actually bites is that Supabase has no push notifications and no crash reporting — so most Supabase apps end up running Firebase anyway.

    5 min read

    The Firebase versus Supabase argument is usually held on database design. Relational versus document. SQL versus a query language that cannot do a join. Open source versus Google.

    All real. None of it is the thing that surprises people three weeks in.

    The thing that surprises people is that Supabase does not do push notifications, and it does not do crash reporting. Both of those are table stakes for a mobile app, and the standard answer to both is Firebase. So a large share of "we chose Supabase" apps are running two backends, which is a decision worth making deliberately rather than discovering.

    The short version

    Choose Firebase if your app is mobile-first and you want one vendor for auth, data, push, crash reporting and analytics. The offline story is the best in the business and you will not assemble it yourself.

    Choose Supabase if your data is genuinely relational, you want SQL and real joins, you care about being able to leave, or you have a web app sharing the same database.

    Either way, expect Firebase Cloud Messaging in your app. It is how Android push works. There is no route around it.

    What each one is actually good at

    Firebase's real advantage is offline. Firestore's local persistence is not a cache you manage — writes made on a plane are queued, applied locally so the UI updates immediately, and reconciled when the connection returns. Your code does not branch on connectivity. For a mobile app used on real networks, this is worth more than most feature comparisons give it credit for, and it is the single hardest thing to replicate on top of Postgres.

    Firebase also gives you Cloud Messaging and Crashlytics, both free, both the default choice in their categories. And it hands you a working auth system with Google, Apple, email and phone sign-in.

    Supabase's real advantage is that it is Postgres. Not "like a database" — an actual Postgres instance you can connect to with any client, run migrations against, join across, aggregate in, and take somewhere else if you need to. Row Level Security means your access rules live in the database rather than in a rules file that only one product understands.

    If your data has relationships — users belong to teams, teams own projects, projects have members — Firestore will make you denormalize it and then maintain the denormalization by hand forever. Postgres will just do it.

    The comparison that matters for a Flutter app

    Firebase Supabase
    Data model Document (Firestore) Relational (Postgres)
    Offline persistence Built in, excellent Roll your own
    Push notifications FCM, first party None — use FCM anyway
    Crash reporting Crashlytics, free None — use Crashlytics or Sentry
    Complex queries Denormalize instead Full SQL
    Self-host / exit No Yes
    Cost shape Per operation Per compute tier

    That cost row deserves a sentence, because the two fail differently. Firebase bills per read, which is invisible while you are building and occasionally alarming at scale — a badly shaped listener on a list screen can bill thousands of reads per session. Supabase bills for compute tiers, which is predictable until you outgrow one and step up.

    Neither is cheaper in general. Firebase is cheaper for small and spiky. Supabase is cheaper for steady and query-heavy.

    The two-backend reality

    Say you pick Supabase. Your data is in Postgres, auth is Supabase Auth, storage is Supabase Storage. Good.

    Now you need push notifications. Supabase's own documented answer is an Edge Function that calls Firebase Cloud Messaging's HTTP v1 API. So you add a Firebase project, add the FCM SDK to your Flutter app, manage the APNs key, store and clean up device tokens in Postgres, and write the Edge Function that bridges the two.

    Then you need crash reporting, and you add Crashlytics or Sentry.

    This is not an argument against Supabase. It is a normal, well-documented setup and plenty of good apps run it. It is an argument against expecting Supabase to be one vendor the way Firebase is one vendor. You are choosing Postgres and accepting a second SDK for the mobile-specific parts.

    Choosing Firebase is the reverse trade: one vendor, one SDK surface, and a database that will fight you the first time you need a join.

    How to decide in one question

    Will your data need joins?

    If yes — teams, permissions, anything with a many-to-many in it, anything you will want to report on — go Supabase and accept FCM alongside it. Denormalizing a relational model into Firestore is a tax you pay on every feature, forever.

    If no — a per-user document store, a feed, a list of things that belong to one person — Firebase is less work end to end, and the offline behaviour is free.

    Everything else, including "open source" and "vendor lock-in", is a real consideration but a smaller one than that.

    Either way, the Flutter side is the same work

    Whichever backend wins, your app still needs the same layer on top: a sign-in flow with Google and Apple, session handling that survives a token refresh, a profile people can edit, account deletion that Apple requires, a repository layer that does not leak the backend SDK into your widgets, and the whole push notification permission and deep-link dance.

    That layer is identical in shape regardless of what is behind it — which is exactly why it should not be rewritten per project, and exactly where an AI agent will happily generate something that works and leaks.

    ShipAppFast is built so this is a choice rather than a rewrite. Authentication, data and storage sit behind a repository layer with Firebase, Supabase and custom API implementations already written, and the screens above it do not know or care which one is connected. Push, crash reporting, analytics and the subscription layer are wired regardless. You pick the backend, not the architecture.

    shipappfast.site