What is a BaaS and why self-host it?
A Backend-as-a-Service (BaaS) bundles everything a modern application needs on the server side into a single product: database, authentication, file storage, serverless functions, and real-time communication. Firebase popularized this model, but its proprietary nature raises concerns about cost, GDPR compliance, and vendor lock-in.
Self-hosting an open-source BaaS on your own VPS gives you full control over your data, eliminates per-request fees, and lets you meet data residency requirements. Supabase and Appwrite are the two most mature solutions in this space.
Supabase vs Appwrite — 12-criteria comparison
| Criterion | Supabase | Appwrite |
|---|---|---|
| Database | PostgreSQL | MariaDB (≤ 1.8), PostgreSQL (2.0+) |
| Minimum RAM | 4 GB | 2 GB |
| Recommended production RAM | 8 GB | 4 GB |
| Number of containers | ~13 | ~19 |
| Main port | 8000 (Kong API Gateway) | 80 / 443 (Traefik) |
| Admin port | 3000 (Studio) | 80 / console (Traefik) |
| Included services | Auth, PostgREST, Realtime, Storage, Edge Functions, Studio | Auth, Databases, Storage, Functions, Messaging, Realtime |
| Auth providers | 15+ | 30+ |
| Functions runtime | Deno only | 30+ runtimes (Node, Python, PHP, Go, Dart, Ruby, Bun…) |
| Client SDKs | JS, Python, Swift, Kotlin, Flutter, C# | JS, iOS, Android, Flutter, React Native, Web |
| Realtime | WebSocket via Realtime service | WebSocket via Appwrite Realtime |
| License | Apache 2.0 | BSD 3-Clause |
Deploying Supabase on a VPS
Step 1 — Clone and configure
git clone --depth 1 https://github.com/supabase/supabase
cd supabase/docker
cp .env.example .envOpen .env and set at minimum POSTGRES_PASSWORD, JWT_SECRET, ANON_KEY, and SERVICE_ROLE_KEY.
Step 2 — Start the stack
docker compose up -dFull startup takes 60 to 120 seconds. Kong may return 502 errors during the first 30 to 60 seconds — this is normal. Wait until all containers are healthy.
Step 3 — Verify
Access Studio at http://your-ip:3000. Test a simple API call:
curl http://your-ip:8000/rest/v1/ -H "apikey: YOUR_ANON_KEY"An empty JSON response {} confirms PostgREST is responding through Kong.
Step 4 — Verify startup
Check all services are healthy:
docker compose psAccess Supabase Studio at http://YOUR_VPS_IP:3000 and create your first project.
Deploying Appwrite on a VPS
Step 1 — Run the interactive installer
docker run -it --rm \
--volume /var/run/docker.sock:/var/run/docker.sock \
--volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
--entrypoint="install" \
appwrite/appwrite:latestThe wizard asks for your domain and ports, and generates a docker-compose.yml tailored to your environment.
Step 2 — Wait for database migrations
On first startup, Appwrite runs its MariaDB migrations. This process takes 2 to 5 minutes and results in temporary 503 errors — this is expected. Follow progress with docker compose logs -f appwrite.
Step 3 — Create the admin account
Once migrations are complete, access http://your-domain/console. Create your first admin account, then your first project.
Step 4 — Create the admin account
Access http://your-domain/console and create the first administrator account, then your first project. On first boot, database migrations run and take 2 to 5 minutes — do not restart.
Authentication — Provider Comparison and OAuth
Both platforms handle email/password and phone number (SMS OTP) authentication. Appwrite supports 30+ OAuth2 providers versus 15+ for Supabase.
Supabase uses GoTrue as its authentication service — a lightweight daemon written in Go. Appwrite integrates its own Auth service configurable from the web console per project, with fine granularity per provider.
For mobile applications requiring OAuth deep links, Appwrite offers better native integration through its dedicated iOS and Android SDKs.
Serverless Functions — Deno vs 30+ Runtimes
Supabase Edge Functions run exclusively on Deno — the modern JavaScript/TypeScript runtime. Deno offers security by default (explicit permissions), native TypeScript support, and a growing module ecosystem.
Appwrite Functions support 30+ runtimes: Node.js, Python, PHP, Ruby, Go, Dart, .NET, Java, Kotlin, Swift, Bun, and more. Each runtime is an isolated Docker container. This flexibility is a major advantage for polyglot teams.
Real-Time and File Storage
Real-time. Both platforms use WebSockets. Supabase exposes PostgreSQL changes in real time via its Realtime service (logical replication). Appwrite Realtime covers events on documents, files, and teams — less tied to the underlying database and therefore more portable.
Storage. Supabase Storage uses an S3-compatible API with RLS access policies directly from PostgreSQL. Appwrite Storage offers team- and user-based permissions, simpler to configure.
Appwrite: 503 error on first launch — wait for migrations
If the Appwrite console shows a 503 error or remains inaccessible in the first few minutes, do not restart the containers. Appwrite runs its MariaDB migrations on first startup, taking 2 to 5 minutes. Wait for Migrations completed before accessing the interface. Restarting containers during this phase will corrupt the database and require a full reinstall.
Supabase: 502 Bad Gateway from Kong on startup — normal behavior
Kong may return 502 errors during the first 30 to 60 seconds after docker compose up -d. This is normal and transient. Wait until docker compose ps shows all containers as healthy. If 502s persist beyond 2 minutes, inspect Kong logs with docker compose logs kong.
Decision guide — Supabase or Appwrite for your project?
Choose Supabase if: your application is web-first, your team knows PostgreSQL, you're migrating from Firebase, or you need an auto-generated REST API from your database schema (PostgREST).
Choose Appwrite if: you're building a mobile (iOS/Android) cross-platform application, your team works in multiple languages and wants to choose its function runtimes, or you prefer a more accessible admin interface without deep SQL knowledge.
On a VPS with 4 GB RAM, Appwrite offers more headroom (requires 2 GB, recommends 4 GB) versus Supabase which uses its 4 GB minimum from startup.
Common errors and fixes
- Supabase — 502 Bad Gateway (Kong): wait 30-60s for all services to be
healthy. If persistent:docker compose restart kong. - Supabase — Realtime
could not connect to the database: restart withdocker compose restart realtime. - Appwrite — 503 on startup: migrations in progress (2-5 min). Do not restart containers.
- Appwrite —
docker compose down -v: DANGER — deletes all data volumes. Never run in production. - Supabase — PostgREST
relation not found: rundocker compose exec meta pgrst-reloadto reload the schema cache. - Appwrite —
SMTP_HOSTnot configured: add_APP_SMTP_HOSTand related variables in.envand restart. Required for invitation emails.
Conclusion: two excellent BaaS platforms, two different philosophies
Supabase and Appwrite are both solid choices for self-hosting an open-source BaaS on your VPS. Supabase shines through its PostgreSQL depth, auto-generated API, and polished Studio. Appwrite stands out for its relative lightness, the richness of its function runtimes, and the quality of its mobile SDKs. In both cases, a dedicated VPS with at least 4 GB of RAM and automated volume backups is the foundation of a reliable deployment.