Skip to content
Flutter+Firebase
Stack Integration

Flutter + Firebase Integration Guide

Firebase is the default backend for Flutter apps — Auth, Firestore, Storage, and Cloud Functions all have first-class Flutter SDK support.

Use Cases
  1. Firebase Auth — email/password, Google Sign-In, Apple Sign-In
  2. Firestore real-time listeners updating Flutter UI automatically
  3. Firebase Storage for user image and file uploads
  4. HTTPS Callable Cloud Functions triggered from Flutter
Implementation

Initialize Firebase in main() with await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform). Use StreamBuilder with Firestore snapshots for real-time UI. Firestore security rules are your authorization layer — write them before production. For Stripe or other payment logic, use HTTPS Callable Cloud Functions — never put payment logic in the Flutter client. Google Sign-In requires SHA fingerprints registered in Firebase console; test on a physical device.

In detail

How the pieces connect

Flutter is the client; Firebase is the backend it talks to over the wire. The firebase_core plugin boots the connection in main(), then each product plugin (firebase_auth, cloud_firestore, firebase_storage, cloud_functions) opens its own channel to Google's servers. Auth issues a signed JWT that the SDK attaches to every Firestore, Storage, and Functions request automatically, so identity flows through without you wiring tokens by hand. Firestore pushes data the other way: a Query.snapshots() stream stays open and emits a new QuerySnapshot whenever a matching document changes server-side. Wrapped in a StreamBuilder, that turns a backend write into a UI rebuild with no manual refetch. Cloud Functions sit beside this for anything the client must not own — Stripe calls, privileged writes — reachable through FirebaseFunctions.instance.httpsCallable('name').

Production gotchas

Firestore security rules are the only thing standing between a user and everyone's data — the client SDK runs with whatever the signed-in user can reach, so an empty or allow read, write: if true ruleset means a public database. Write rules that check request.auth.uid against the document owner before you ship. Offline persistence is on by default on mobile, which is convenient but means snapshots() can serve cached data first and the network copy after; check metadata.isFromCache when freshness matters. HTTPS Callable Functions cold-start, so the first call after idle is slower — expect a second or two and show a loading state rather than a frozen button. Google Sign-In silently fails in release builds if the release SHA-1 and SHA-256 fingerprints aren't both registered in the Firebase console, and debug fingerprints don't cover release. Apple Sign-In needs the capability enabled in Xcode and the Service ID configured.

Keeping secrets and payment logic server-side

Anything bundled into a Flutter build ships to the user's device and can be decompiled, so treat the client as untrusted. Firebase config values (API key, project ID in firebase_options.dart) are not secrets — they identify the project, and security rules do the actual gating. Real secrets — a Stripe secret key, third-party API tokens — belong only in Cloud Functions, read from the Functions runtime environment, never compiled into the app. Payment flows follow the same rule: the client requests a charge through a Callable Function, the function talks to Stripe with its secret key and verifies the amount server-side, and Stripe webhooks (which the client never sees) confirm the final state. I built this exact pattern for BookBed, a booking SaaS on Flutter, Firebase, and Stripe — the Flutter app never touches the Stripe secret key or trusts a client-reported price.

When this combo fits — and when it doesn't

Flutter plus Firebase fits when you want one codebase across iOS, Android, and web, real-time data, and authentication without standing up your own servers — the SDKs are first-party and the wiring is short. It's a strong default for SaaS dashboards, booking and messaging apps, and anything where Firestore's live listeners replace a polling layer. It fits less well when your data is heavily relational with multi-table joins and transactions across many entities — Firestore is a document store with no SQL joins, and modeling that forces denormalization and fan-out writes. Aggregations and full-text search also live outside Firestore (you bolt on counters, Cloud Functions, or a search service). If you need a relational schema or complex server queries, a Postgres-backed stack is the cleaner choice; pick Firebase when real-time and fast iteration outweigh relational rigor.

Live ExampleFlutterFlow Templates — Case Study
Other integration guidesView all →
Related

Need this built?