database · tutorial · comparison
Supabase Starter That Keeps Your Exit Open
Supabase Auth plus Postgres plus storage — wired with portable seams so the bundle never becomes a trap. The honest starter inside.

My Supabase honeymoon ended at the invoice
Month one with Supabase is bliss.
Auth in an afternoon.
Postgres without provisioning.
Storage with a dashboard.
Month four brings the egress line. Month six, the row-count tier math. Month nine, the quiet realization that Auth users, storage paths and row policies have woven the app into one vendor's shape.
Nothing is overpriced in isolation. Everything grows load-bearing in combination.
Leaving means an auth migration, URL rewrites and policy translation. A quarter nobody budgets, because "free tier" made deciding feel unnecessary.
Enjoy the bundle fully. Plan the exit first.
Bundled or seamed
| Layer | Welded, the typical path | Seamed |
|---|---|---|
| Auth users | Supabase-only sessions | Your own user rows |
| Storage URLs | Supabase paths everywhere | Your own domain, portable |
| Access logic | Row policies as the only guard | App guards first, policies optional |
| Queries | Supabase-JS idioms inline | Shared actions, portable |
| Exit effort | Large | Bounded by design |
The bundle teaches three lessons.
Row policies become architecture by accident. They start as security and end as business logic. Tier checks, ownership rules, visibility filters. Logic that exists nowhere else.
App guards first. Policies second.
Storage paths are forever addresses. Every vendor URL baked into rows, emails and caches is a migration line item. Your own domain costs the same effort today and moves free tomorrow.
Auth depth is the deepest hook. Sessions keyed to your own user rows migrate as data. Vendor-shaped sessions migrate as projects. Own identity, rent features.
What to do
Own identity. Rent the database.
Sign-in runs through the kit's own Google and email-link flows. A Supabase adapter stores users in your Supabase tables, but the logic about who is who stays in the app.
The vendor holds rows. Your app holds the meaning.
OAuth identities re-link by email after any future move. Magic links work against migrated rows immediately.
Store files at addresses you control.
Uploads go from the browser straight to object storage like R2 or S3, and are served from your own domain. The database stores your addresses, never a vendor's paths.
Storage then migrates with a DNS change and a copy.
Guard in app code first. Add policies as armor.
The app checks ownership and paid access in code, which is reviewed, tested and portable. Supabase's row-level policies can sit on top as extra protection, but the kit does not depend on them.
When engines change, app guards move as they are.
Bundled or seamed, over time
| Event | Native path | Portable alternative |
|---|---|---|
| Download traffic grows | Pay and wince | Files already on your own storage |
| Tier pressure | Upgrade or migrate | Switch engines |
| An auth export | A project | Rows move as data |
| Policy translation | A rewrite from scratch | App guards carry over |
Seams cost upfront thought. URL design, app-level guards, identity mapping. Roughly an afternoon per layer, before any pain exists.
BoringPush does not publish exit timings. Rehearse your own.
Know this first
BoringPush does not publish exit timings. It ships no realtime layer.
Rehearse your own exit before you need it.
Why BoringPush is the way to do this
Enjoy Supabase. Don't depend on it.
BoringPush stores users in your tables, serves files from your own addresses and guards access in app code.
The bundle is optional. Moving stays possible.
FAQ
Is Supabase still worth it versus SQLite first?
For Supabase-committed teams, absolutely: managed Postgres, a dashboard and quick setup are real advantages. For engine-agnostic solos, start with SQLite and switch later if needed. The seams serve both: committed users get safety rails and future-switchers keep the door open.
How do realtime subscriptions fit?
Treat Supabase realtime as the current transport and keep the meaning of a subscription in app code. BoringPush does not ship a realtime layer, so if you add one, keep a polling fallback for engines without push.
Should row-level policies be strict if app guards already check?
Defense in depth earns its keep exactly once, on the day a bug bypasses app code. Strict policies plus primary app guards are belt and suspenders, each cheap. Document the intent so policies can be rewritten for another engine.
What is hardest to migrate if I leave?
Habit, not data. Dashboard workflows such as the table editor and log tailing have no equivalent at the same polish. Rows, files and guards move quickly; fingers take a month.
Can I run hybrid, with managed auth and local data?
It is a legitimate steady state when chosen on purpose. BoringPush's own auth plus a local SQLite file, or Supabase for data only, are both supported. Document why you chose it and revisit it yearly.
When should the exit be tested, not just built?
Once a year, on staging only: export users, copy a storage bucket and translate one policy, timed. Untested exits are intentions, and drilled exits are options.
Keep reading
- SQLite vs Mongo vs Supabase: 2 Triggers End the Debate — when the exit actually triggers
- One Auth Flow, Three Databases, Zero Forced Logouts — identity surviving flips
- Switch Databases With One Line (Zero Rewrites) — the flip both posts rehearse
+ all the boring stuff (analytics, auth, SQLite ↔ Supabase, full marketplace, webhooks)
Command from your phone.
Built so autonomous AI agents build what you want without breaking what's already paying you.
- Built-in analytics — cookie-free mode, $0 forever, no PostHog bill
- SQLite ↔ Supabase: one setting, same field names
- Full digital marketplace & feedback boards included
- 3 payment rails: Stripe, LemonSqueezy & Dodo Payments
- Agent fences: lint gate, read-only data access, auto-rollback
- Ship from your phone via SSH & WireGuard/Tailscale in under a minute
$199
Get BoringPushOne-time payment · Lifetime updates · Unlimited projects.
Keep reading


