Comparison
Baselyra against Supabase, Appwrite and Firebase.
Written to be useful rather than flattering. Supabase is the more capable product and this page says so in several places; so is Firebase, at a scale Baselyra is not designed for. What follows is where each one wins, so you can pick on the axis that matters to you instead of on a table that loses nowhere.
The short version
Pick on this, not on the feature count
Choose Baselyra when
You want RLS-backed APIs over your own Postgres on a small box you control, you would rather read one process than operate thirteen, and the missing pieces — edge functions, image transforms, replicas — are ones you do not need.
Choose Supabase when
You want the same Postgres-and-RLS model with far more around it: managed hosting, edge functions, image transforms, dozens of sign-in providers, read replicas, branching, pooling at scale and an ecosystem with answers already written.
Choose Appwrite when
You want a batteries-included backend with server-side functions in many runtimes, messaging, a mature mobile SDK story and a permissions model per document rather than SQL policies — and you are happy to run MariaDB and Redis.
Choose Firebase when
You want zero operations, global scale from day one, offline-first mobile sync and the deepest client SDKs of the four — and you accept a proprietary, hosted-only platform with a metered bill and a NoSQL data model.
Feature by feature
The whole table
Self-hosted configurations for Supabase and Appwrite, because that is the comparable thing. Firebase has no self-hosted form at all, which is itself one of the rows.
| Baselyra | Supabase (self-hosted) | Appwrite (self-hosted) | Firebase | |
|---|---|---|---|---|
| Containers to run | 2 | ~12–15 | ~10–20, server plus workers | n/a — hosted only |
| Idle memory | ~400–600 MB | ~2–4 GB | ~2–3 GB | n/a |
| Fits a 1 GB VPS | yes | no | no | n/a |
| Datastore | Postgres 17 | Postgres | MariaDB, plus Redis | Firestore / RTDB, document store |
| SQL you can run | yes, it is your database | yes | not the intended interface | no |
| Authorisation model | Postgres RLS | Postgres RLS | Per-document permission strings | Security Rules DSL |
| REST API over your tables | built in, PostgREST-compatible subset | PostgREST, the full surface | Appwrite SDK protocol | SDK, not REST over tables |
| Realtime | changes, broadcast, presence, RLS re-checked per subscriber | changes, broadcast, presence | yes | yes, best-in-class offline sync |
| File storage | local disk, signed URLs, Range and ETag | local or S3 | local or S3 | Cloud Storage |
| Image transformations | no | yes, imgproxy | yes, built in | via an extension |
| Edge / server functions | no — Postgres functions over RPC only | yes, Deno | yes, many runtimes | yes, Cloud Functions |
| Sign-in providers | 7 | far more — dozens | far more — dozens | many, plus Apple and phone at scale |
| Phone / SMS sign-in | yes, 6 back ends | yes | yes | yes |
| Password migration in | bcrypt preserved from Supabase and Postgres | via your own script | via your own script | via your own script |
| Guided import from other backends | Supabase, Postgres, Appwrite, Firebase, SQL dump | Postgres sources | limited | no |
| Admin console | yes, in the same process | yes, its own container | yes | yes, hosted |
| Operator accounts and roles in the console | accounts, three built-in roles, custom capability sets | self-hosted: one shared dashboard login | teams and roles | Google Cloud IAM |
| AI assistant over your schema | yes, DeepSeek, optional | yes | partial | yes, Gemini |
| Read replicas and failover | no | yes | via your own MariaDB setup | managed and global |
| Connection pooling at scale | one pg pool | Supavisor | yes | n/a by design |
| Branching / preview environments | no | yes | no | multiple projects |
| Multiple projects per instance | not yet — the plumbing exists, nothing creates a second one | yes | yes | yes |
| Managed hosting available | no | yes | yes | yes, only |
| Runs without vendor accounts | yes | yes, self-hosted | yes, self-hosted | no |
| Telemetry in the default install | none | a self-hosted analytics pipeline ships in the stack | configurable | n/a, it is the vendor |
| Licence | Apache-2.0 | Apache-2.0 for most components | BSD-3-Clause | proprietary |
| Runtime dependencies of the server | 8 npm packages | Kong, GoTrue, PostgREST, Realtime, Storage, imgproxy, meta, Vector… | Traefik, MariaDB, Redis, ~10 workers | n/a |
| Upgrade | compose pull && up -d | coordinated across services | coordinated across services | nothing to do |
| Ecosystem, tutorials, answers | new and small | large | large | enormous |
| Community support | a repository | Discord, forums, paid support | Discord, forums, paid support | paid support, huge Q&A corpus |
green is the stronger position on that row, amber is qualified, grey is absent. Several of the green cells are not in the Baselyra column, which is the point of publishing the table.
The honest part
Where the others are genuinely ahead
A comparison that loses nowhere is not believed, and rightly. These are the reasons to not pick Baselyra, written by the people who made it.
Supabase
- Managed hosting. Somebody else is on call. That alone outweighs everything on this page for many teams.
- Edge functions. A real deploy target for your own code, which Baselyra simply does not have.
- More sign-in providers by a wide margin, Apple included.
- Image transforms, S3 storage, read replicas, branching, Supavisor. Each is a whole capability Baselyra lacks.
- The full PostgREST surface rather than a compatible subset, and a much larger ecosystem of libraries and answers.
- Maturity. More people have hit the sharp edges and written about them.
Appwrite
- Server-side functions in many languages, deployed through the console.
- Messaging — push, email and SMS as a first-class product rather than an auth detail.
- A mature mobile SDK story, including offline affordances Baselyra has none of.
- Dozens of OAuth providers and a per-document permission model some teams find easier to reason about than SQL policies.
- A hosted Cloud, and a large community.
Firebase
- Zero operations, global scale. Nothing here competes with that and nothing here tries to.
- Offline-first sync that genuinely works on a phone in a tunnel. Baselyra’s realtime reconnects; it does not reconcile.
- The deepest client SDKs of the four, on every platform that matters.
- Analytics, Crashlytics, Messaging, Remote Config — a product suite, not a backend.
- Cloud Functions and an enormous body of existing answers.
The other direction
Where Baselyra is genuinely ahead
It fits on the box you have
Two containers and a few hundred megabytes. A self-hosted Supabase or Appwrite wants several gigabytes before it serves a request, which is the difference between a 1 GB VPS and a bill.
One process to debug
When a request behaves oddly there is one log and one codebase — eight runtime dependencies, no ORM, no broker, no sidecar. Not simpler in theory: smaller in fact.
One upgrade, not a matrix
docker compose pull
&& docker compose up -d. No version compatibility to check across a fleet of
services that must agree with each other.
Migration in, with passwords
Supabase and Postgres bcrypt hashes are carried across verbatim and retire themselves to scrypt as users return. No reset email to anybody. None of the other three offers a guided import from its competitors.
The control plane is outside
Studio accounts live in a separate database that a project connection cannot read, even holding the service key. Postgres has no cross-database joins without FDW, so it is a boundary rather than a convention.
Nothing is metered
No MAU band, no egress meter, no invocation count, no project fee, no pausing when idle, no telemetry. Your bill is the box, and it does not move when a job loops.
Coming from Supabase
How much of what you know transfers
| Concept | In Baselyra |
|---|---|
createClient(url, anonKey) | the same call |
.from().select().eq().order() | the same builder |
Embedded resources author:users(name) | one level deep |
auth.uid() in policies | identical |
| Anon key and service key | identical roles and meaning |
storage.from().upload() | the same shape |
Realtime channels and postgres_changes | the same frames |
Prefer: return=representation | supported |
| Edge functions | absent — use Postgres functions over RPC |
| Image transform query parameters | absent |
| Supabase CLI, migrations, branching | absent — plain SQL files in db/ |
@supabase/supabase-js.
It is deliberately shaped like it, which means a port is mostly changing an import and a
couple of option names — not that every method exists.
Decide by running it
Half an hour with a real instance beats any table.
Import a copy of your Supabase project into a throwaway instance and try your three most awkward queries. That answers this page far better than this page does.