Run it on your machine.
Clone and configure
Copy
.env.exampleto.env. The defaults run on one machine.Start it
docker compose up -d --wait. You need Docker Engine 26 and Compose 2.30 or newer, and room for about 26 containers.Claim it
Read the setup code from the logs and create the first account with it: that account is the instance's admin.
Create a database
Open Studio, add a database, branch it and query it.
git clone https://github.com/chelabase/chelabase.git
cd chelabase/infra/compose
cp .env.example .env
docker compose up -d --wait
docker compose logs init-secrets # your setup code
# want a populated demo instead? on a fresh stack:
# docker compose -f docker-compose.yml -f docker-compose.example.yml up -d --wait
# then open http://studio.chelabase.localhost:8000Everything in one place.
Chelabase's core services are built in Rust, and so is Neon's storage engine under Postgres. Accounts live in a small internal Identity service on Better Auth. It all runs together on one machine.
Databases
Postgres 17, each database with its own tenant and timeline and each branch its own compute, on Neon's storage engine. Postgres clients connect through its proxy with login roles.
Studio
The web console for all of it: projects, databases, the branch tree, the table and SQL editors, members, keys and your app's users.
Auth
Signs in Studio members and your app's own users, with helpers for row-level security policies.
Realtime
Pushes changed rows and presence to Studio over a WebSocket as keys only, so each row is read again as the viewer's role.
Gateway
The single front door. It checks every request's credential, a member's token or a data API key, and forwards it to the right service.
Orchestrator
Serves the Management API, decides who may do what, and keeps the platform's own state.
Worker
Runs the orchestrator's jobs: creating, branching, resetting, merging and deleting databases.
Rest
The data API. It turns a JSON query into SQL and runs it as the key's role, so row-level security decides what each caller sees.
Object storage
S3-compatible buckets for your app's files, guarded by row-level security, with signed and public URLs, a Studio tab, the typed client and webhooks.
CLIComing soon
A command-line tool for setup and management from the terminal: generate types, run migrations and more. Not available yet.
The crab is a nod to Ferris, Rust's mascot. Chela is Greek for claw.
How it compares.
What each platform offers today, from its own docs. Benchmarks come later.
Comparison preview — benchmarks coming later
| Chelabase | Supabase | Firebase | Neon | PlanetScale Postgres | PlanetScale MySQL | |
|---|---|---|---|---|---|---|
| Postgres | Yes | Yes | Yes | Yes | Yes | MySQL |
| Copy-on-write branches | Yes | Schema-only branches | No | Yes | No | No |
| Schema merge between branches | Yes | Partly | No | No | No | Yes |
| Protected branches | Yes | No | No | Yes | Partly | Yes |
| Point-in-time restore | Yes | Yes | Yes | Yes | Yes | No |
| Self-hostable | Yes | Partly | No | Partly | No | No |
| Team access enforced by Postgres | Yes | Dashboard roles | Cloud IAM | Org roles | Org roles | Org roles |
| Typed query API | Yes | Yes | Yes | Yes | No | No |
| App-user auth, with SSR | Yes | Yes | Yes | Yes | No | No |
| Table and SQL editors | Yes | Yes | Partly | Yes | Partly | Partly |
| Live rows in the editor | Yes | No | Yes | No | No | No |
| Realtime for your app | Coming soon | Yes | Yes | Yes | No | No |
| Object storage | Yes | Yes | Yes | Yes | No | No |
From each product's docs, November 2026. Neon's realtime and object storage are in beta; Neon's schema diff compares branches but doesn't merge them. Supabase merges a branch into production through a schema diff, and self-hosted Supabase runs one project without branching or point-in-time restore. PlanetScale merges schema through deploy requests on MySQL (Vitess) only. Firebase's Postgres is SQL Connect (Cloud SQL for PostgreSQL, with typed SDKs). Neon's storage engine is open source, but its control plane isn't.
Manage it from one console.
Studio holds the whole database: tables, SQL, roles, keys and your app's users. A change shows as the SQL it will run, before it runs.
Structure changes you can read first
The table editor stages column, index and constraint changes, shows them as the exact SQL with a dry run, and applies them in one transaction.
A SQL editor with a guard
It asks before risky statements, runs as the owner or as a role you pick, and keeps saved queries per database, shared with the project, with your run history in your browser.
Credentials you can see again
Login role passwords are encrypted at rest and can be revealed later, so a lost connection string doesn't mean a reset.
Security in plain view
Studio flags tables the data API can reach without row-level security, and says when you're running as the owner.
Bring your team in.
Invite people, group them into teams, and grant each team the Postgres roles it may act as. Postgres' own privileges decide the rest, so a schema can belong to one team.
Teams with live grants
Change a team's grant and every member changes with it. Per-database overrides narrow it for one person.
Protected branches
Protect a branch from delete and reset. Protecting first reviews any code an untrusted role could run in an Admin's session.
Work side by side
The table editor shows live rows and who else is looking, and a save fails rather than overwrite someone's change.
An access log
Every invite, grant, approval and removal is recorded with who did it and what changed, never secrets.
Build your app on a typed API.
One endpoint, POST /data/v1/query, and a client with types fetched from your schema. Public-key queries run as anon or authenticated, so row-level security decides what each user sees. The client isn't on npm yet: use it from the repository.
Auth for your app's users
Sign-up, sign-in and sessions, with helpers for row-level security policies.
Server rendering
Browser and server clients see the same signed-in user through cookies, and the refresh token stays HttpOnly.
Plain Postgres too
Migrations, ORMs and
psqlconnect over the Postgres protocol with a login role.
orders.tsimport { createServerClient } from "@chelabase/client/server";
import { type Database, types } from "./db";
// ./db comes from GET /data/v1/types
const db = createServerClient<Database>({ url, key, types, cookies });
const user = await db.auth.getUser();
const mine = await db
.from("orders")
.select("id", "total")
.where({ customer_id: user.id });
// sales.orders, only the signed-in customer's rowsBranch it. Reset it. Restore it. Merge it.
Every database starts with one branch, main. Try a change on a copy of real data, then bring it home.
Branch
Copy any branch as it is now, or as it was at any point in its history window (seven days by default). The copy is copy-on-write, so no data is copied: it's ready as soon as its compute starts, with its own endpoint and password.
preview is a copy-on-write copy of main as it was 3 days ago. It shares main's pages until either side writes.
Start with the Quickstart.
Create a database, add a table, and query it from your app with the typed client.