- Supabase local dev = a 12-container, 2.3 GB Docker stack. tinbase serves the same APIs from one 58 MB process. No Docker.
- It’s real Postgres 17 — RLS,
auth.uid(), jsonb, triggers, foreign keys all behave like hosted Supabase. - The official supabase-js SDK works unchanged (168/168 integration tests pass).
- The whole backend — database included — can run inside a browser tab.
- Open source, MIT. Try it:
npx tinbase start
The problem
You know the drill. supabase start, then Docker pulls Postgres, PostgREST, GoTrue, Storage, Realtime, Studio… twelve containers, 2.3 GB on disk, ~1.6 GB of RAM under load. All you wanted was to run your app locally.
I love Supabase. I did not love paying a 2 GB tax to write a todo app on the train.
What tinbase does instead
One process. Same wire protocols:
Install footprint Memory under load Supabase local (12 containers) 2,291 MB 1,626 MB tinbase (single binary) 92 MB 66 MB tinbase (native) 36 MB 100 MBnpx tinbase start
Enter fullscreen mode Exit fullscreen mode
~2 seconds later you’re serving requests. There’s also a single 58 MB executable that needs no Node, npm, or Docker on the target machine.
Your code doesn’t change
This is the whole point. tinbase implements the PostgREST query grammar, GoTrue auth flows, the Storage API, and the Realtime Phoenix protocol — verified by running the official SDK against it:
import { createClient } from '@supabase/supabase-js'
const supabase = createClient('http://127.0.0.1:54321', ANON_KEY)
await supabase.auth.signUp({ email, password })
await supabase.from('todos').insert({ title: 'hello' })
const { data } = await supabase
.from('todos')
.select('*, author:users(name)')
.eq('done', false)
supabase.channel('feed')
.on('postgres_changes',
{ event: 'INSERT', schema: 'public', table: 'todos' },
handleNewTodo)
.subscribe()
Enter fullscreen mode Exit fullscreen mode
No fork of the SDK. No wrapper. No different query language. RLS runs with your JWT claims applied, so auth.uid() policies work as-is — and Realtime does per-subscriber RLS filtering, so users only get change events for rows they can see.
Auth covers email/password, anonymous, OTP, magic links, password recovery, and OAuth (Google/GitHub + generic) with PKCE. Edge Functions run in-process via supabase.functions.invoke(). Webhooks, cron.schedule(), and a pgmq subset are in there natively — no pg_net/pg_cron/pgmq extensions to install. And a Supabase-Studio-style dashboard ships at /_/.
The weird part: it runs in a browser tab
Every service in tinbase is a pure (Request) ⇒ Response fetch handler on top of a swappable DB engine:
supabase-js (unmodified)
│
▼
one (Request) ⇒ Response handler
├─ /rest/v1 (PostgREST)
├─ /auth/v1 (GoTrue)
├─ /storage/v1 (Storage)
├─ Realtime (WebSocket)
├─ /functions/v1 (Edge Fns)
└─ /_/ (Studio)
│
▼
DbEngine adapter
├─ native → embedded Postgres 17
├─ wasm → PGlite (Postgres in WASM)
└─ pg-mem → pure JS, in-memory
Enter fullscreen mode Exit fullscreen mode
In Node, that handler is an HTTP + WebSocket server. In the browser, you hand it to supabase-js as a custom fetch — and the entire backend, Postgres included, runs in-process in the tab. No server. No cloud. You can play with it at tinbase.dev/browser.
It’s not a dead end
tinbase reads supabase/migrations/*.sql and seed.sql exactly like the Supabase CLI, tracked in the same table. Outgrow it? Push the same files to hosted Supabase and keep moving. You can also point it at a Postgres you already run with --database-url.
Why we built it
tinbase came out of building RapidNative and lifo, with a stubborn goal: run an entire dev stack — database, auth, storage, realtime — in the browser and on phones, with no VMs and no cloud behind it. Cutting the backend down to a single process was step one; making that same process run inside a tab was step two. Somewhere along the way it turned into a genuinely useful Docker-free replacement for local Supabase dev, so we open-sourced the whole thing (MIT).
Honest caveats
It’s alpha (v0.10.0). Built for local dev, prototypes, and embedded/browser use — not production. 168/168 integration tests pass across both engines, but if you hit an API edge we haven’t covered, open an issue.
Try it
npx tinbase start
Enter fullscreen mode Exit fullscreen mode
GitHub: github.com/tinbase/tinbase
What would you build if your whole backend fit in a browser tab? Drop a comment — especially if you try the browser engine, I want to see what you make with it. 🚀
답글 남기기