A multi-tenant, self-hostable Backend-as-a-Service on real Postgres.
The developer experience of a managed platform, the lightweight footprint of an embedded database, and true multi-tenancy — on infrastructure you own.
In Old Norse law, a hauldr was a freeholder — someone who held their land outright, by inherited right, answering to no lord. Hauldr is a backend you hold the same way: your data, your Postgres, your box. No landlord.
Hauldr is an open-source backend platform you run yourself. It gives a small team the same building blocks a managed BaaS would — authentication, a real SQL database with row-level security, file storage, realtime, and a typed client SDK — but each tenant project is isolated, lightweight, and provisioned in seconds, all on top of standard, battle-tested open-source components.
It is designed for the shape of work where you run many small applications (one per client, per product, per internal tool) and want each one to have a proper database with real auth and access control — without paying the per-app overhead of a heavyweight stack or the per-seat bill of a hosted vendor.
Three moving parts:
- Control plane — a self-hosted panel (Supabase-like UX) plus a management API for creating and operating projects.
- Shared data plane — a Postgres cluster fronted by a multi-tenant connection pooler, with one database per project.
- Per-project satellites — only the services a given project asks for (auth always; a REST API layer à-la-carte).
The two ends of the spectrum each have a cost:
- Heavyweight managed stacks are excellent but assume one big tenant. Running dozens of small isolated apps means dozens of full deployments, or giving up isolation.
- Embedded single-file databases are wonderfully light, but you eventually hit real ceilings: concurrent writers, true SQL, row-level security, point-in- time recovery, connection scaling.
Hauldr sits in the middle deliberately: heavy things are shared (one Postgres cluster, one pooler, one object store, multi-tenant), light things are per- project and optional. A project is just a database, an auth service, and a JWT secret — measured in tens of megabytes, not gigabytes.
- Shared is heavy, per-project is light and optional. Multi-tenancy lives in the shared plane; each project only carries what it actually needs.
- One auth model, always. Every project ships with its own GoTrue instance and its own JWT secret. Row-level security is always on — access control is enforced by the database, reading the claims from the auth token.
- Real Postgres underneath. No reimplemented query engine. Extensions (pgvector, etc.) are enabled per-database, on demand.
- Scale honestly. A multi-tenant pooler keeps connections under control; tiering lets a project that outgrows the shared cluster move to a dedicated one without changing application code.
- Assemble upstream, don't reinvent. Hauldr builds the panel, the provisioner, the SDK, and the conventions. It never rewrites the database, the pooler, or the auth server — those are proven projects, used as-is.
CONTROL PLANE DATA PLANE (shared)
┌─────────────────────┐ ┌──────────────────────────────────────┐
│ Hauldr Panel │ │ Connection pooler (multi-tenant) │
│ (SQL / tables / │ ── API ──▶│ routes project → database │
│ auth / RLS / │ │ │ │
│ keys / logs / │◀── meta ──│ Postgres (1+ cluster, 1 DB/project) │
│ backups) │ │ ├ db_acme ├ db_shop ├ … │
│ │ └──────────────────────────────────────┘
│ Hauldr API (mgmt) │ ▲ per-project, à-la-carte
└──────────┬──────────┘ │ ┌ Auth (GoTrue) [always]
│ called by │ └ REST (PostgREST) [optional]
your provisioning automation │ realtime = shared WS · storage = S3
Full detail in docs/architecture.md.
The SDK is the layer that makes a decomposed backend feel like one thing. It hides the pooler, the auth server, and the object store behind a small surface:
import { createClient } from "@hauldr/client"
const hauldr = createClient({ url: HAULDR_URL, anonKey: ANON_KEY })
// Auth — full lifecycle (signup, OAuth, magic-link, MFA, reset)
await hauldr.auth.signInWithPassword({ email, password })
// Data — typed queries; the RLS claim is injected for you
const posts = await hauldr.db.query.posts.findMany({ where: { published: true } })
// Files — S3-style upload + signed URLs
const { url } = await hauldr.files.upload("avatars", file)
// Realtime — WebSocket via a shared, multi-tenant Realtime service
hauldr.live.on("posts", (change) => render(change))| Namespace | Backed by |
|---|---|
hauldr.auth |
GoTrue (lifecycle / OAuth / magic-link / MFA) |
hauldr.db |
Typed queries through the pooler (RLS-aware) |
hauldr.files |
Object storage over standard S3 |
hauldr.live |
Shared Realtime over WebSocket (broadcast · presence · changes) |
See docs/sdk.md.
| Doc | What's inside |
|---|---|
| Architecture | The full system: control plane, data plane, satellites |
| Concepts | Glossary and the model behind projects, tenancy, tiering |
| Auth & data | GoTrue, RLS, server actions vs. REST, claim injection |
| Data plane | Postgres, the pooler, migrations, backups, tiering |
| Storage | S3-compatible object storage, buckets, durability |
| SDK | @hauldr/client surface and usage |
| Self-hosting | Bootstrap, "project zero", running the stack |
| Roadmap | Phased delivery plan |
Hauldr is pre-alpha and developed in the open. The foundational architectural decisions are settled. The control plane provisions projects end-to-end — auth always, REST / storage / realtime à-la-carte — over a multi-tenant pooler, and it already runs a real fleet of applications. What's left is operational polish (backups / PITR, tiering, per-project metrics) and a one-click migration path. Expect breaking changes until a tagged release.
See the roadmap for what's coming and in what order.
Hauldr is an assembly of excellent open-source projects:
- PostgreSQL — the database
- Supavisor — multi-tenant connection pooler
- GoTrue — authentication
- PostgREST — optional REST API layer
- Garage — S3-compatible object storage
- Drizzle — the typed data layer in the SDK
Contributions are welcome — see CONTRIBUTING.md. Please also read the Code of Conduct and our security policy.