Backends
Firebase, Supabase, and REST API. When to use each one, what the CLI does, and what you need to do manually.
When you run kasy new, you pick one backend. The app's interface is the same, only the data layer changes. You can migrate later with some effort, but it's best to decide early.
Quick comparison
| Firebase | Supabase | REST API | |
|---|---|---|---|
| External account | Google Cloud with an active Blaze plan | supabase.com (free tier) | None |
| Database | Firestore (NoSQL) | Postgres | Yours |
| Serverless backend | Cloud Functions | Edge Functions | No, you implement it |
| Automatic deploy | kasy deploy (manual) | Automatic in kasy new | Doesn't exist |
| Anonymous login | Automatic (enable in the console) | Automatic (config.toml) | Not supported natively |
| Push notification | No key needed (uses ADC) | Needs a Firebase JSON key | Needs a Firebase JSON key |
| Best for | Wants to get started fast with Google | Wants SQL and open source | Already has their own server |
REST API is more work. The UI is the same as the others, but you implement every endpoint (auth, Stripe/RevenueCat webhooks, push, admin). If this is your first app, consider Firebase or Supabase.
Firebase
What the CLI does in kasy new
- Creates the Google Cloud project (needs the Blaze plan, required by Cloud Functions; it's pay-as-you-go, not a subscription, see Prepare your machine)
- Configures Firebase Auth, Firestore, Cloud Storage
- Adds the debug keystore's SHA-1 automatically
- Downloads
google-services.jsonandGoogleService-Info.plist
What you do manually
After kasy new, open the Firebase Console:
- Authentication → Sign-in method → enable Anonymous (required in the default mode)
- Cloud Messaging → Apple app config → upload the APNs Key
.p8(for iOS push, see Push) - If you'll use forced updates: Remote Config → create
app_latest_versionandapp_min_version(see App update)
Then:
kasy deploy # uploads functions + Firestore rules + Storage rules
kasy run # starts the appWith Firebase and anonymous login (the default), kasy deploy before the first kasy run. Without deploy, the Auth Triggers don't exist on the server: the app creates the anonymous account, but the function that creates the profile never runs.
Supabase
Prerequisite
Log in once before kasy new:
supabase loginWithout this, kasy new fails at deploy time (it links the project, runs migrations, and deploys Edge Functions).
What the CLI does in kasy new
- Creates the Supabase project (or links to an existing one)
- Creates/links a companion Firebase project (FCM + Remote Config)
- Configures Google Sign-In on Supabase Auth (OAuth client in Google Cloud via
firebase deploy --only auth+ credentials via Management API) flutterfire configure+ Android SHA-1 +google_auth_options.dart+ iOS URL scheme- Runs Postgres migrations + RLS only for the features you selected (base + Quick preset modules or your Advanced choices). No Drive in Quick mode. See Database schema (Supabase · Firebase).
- Automatically deploys Edge Functions for those same features (Stripe, RevenueCat, push, AI, admin, etc.)
- Enables anonymous login in
config.toml(enable_anonymous_sign_ins = true) - Disables email confirmation (needed for the anonymous → linked account flow)
What you do manually
- For push notifications: generate and register the Firebase Service Account JSON key (see Push)
- For plan upgrades in Stripe: register the
STRIPE_*secrets (the CLI asks duringkasy new)
Important differences from Firebase
| Topic | Firebase | Supabase |
|---|---|---|
| Enabling anonymous login | Manual console step | Automatic (config.toml) |
| Push notification (FCM) | No key (ADC) | Needs the Firebase Service Account JSON |
| Changing secrets | firebase functions:secrets:set | supabase secrets set |
| Database | Firestore (NoSQL) | Postgres + RLS |
RLS (Row Level Security): Supabase turns on protection on every table. The query SELECT * FROM users only returns your own record, not every user. This is by design and protects against escalation. To list everything (in the admin), use the admin-list-users Edge Function.
REST API
You implement the backend
Kasy gives you the complete Flutter app, but the backend is yours. The kit documents every contract the app expects.
What the CLI does in kasy new
- Generates Flutter with the data layer pointing at REST
- Creates
BACKEND_URLin.vscode/launch.json(you swap in your own) - Generates a
README.mdin the project with every required endpoint
What you implement
| Category | Required endpoints |
|---|---|
| Auth | POST /auth/signup, POST /auth/signin, POST /auth/refresh, POST /auth/social |
| User | GET /users/{id}, PATCH /users/{id}, DELETE /users/{id} |
| Push | receives device tokens, fires FCM (uses the Firebase JSON key) |
| Stripe (if enabled) | POST /webhooks/stripe, POST /stripe/checkout-session, POST /stripe/portal-session, GET /stripe/list-prices |
| RevenueCat (if enabled) | POST /webhooks/revenuecat |
| Notifications | GET/POST /users/{id}/notifications |
| Admin (if enabled) | GET /admin/users, PATCH /admin/feature-requests/{id} |
| AdMob SSV (if enabled) | GET /ads/verify-reward |
| AI Chat (if enabled) | POST /ai/chat |
Full list with payloads in the README.md generated inside your project.
Limitations
- Anonymous login doesn't work natively. The kit throws an error if you try. Two ways out:
- Change
authenticationModetoauthRequiredinlib/environments.dart(recommended) - Or implement
POST /auth/guest, which creates a temporary session
- Change
kasy deployis a no-op on REST API: you deploy the server wherever you wantkasy checkonly validates local config: it doesn't test your backend
Authentication (Bearer token)
The app sends Authorization: Bearer <jwt> on every call. Your server:
- Validates the JWT signature
- Extracts the
sub(user ID) from the payload - Applies permissions from there
See the generated README.md for the full token and refresh-token schema.
Every feature (push, ads, admin, paywall) works on all three backends. The difference is just where the data lives and who implements the server.
Last updated on 08/02/2026

