Deployment guide

Supabase vs Appwrite: Choosing Your Open-Source BaaS on a VPS

Deploy on a VPS Cloud →

Comparison

Supabase vs Appwrite: Choosing Your Open-Source BaaS on a VPS

Supabase and Appwrite are the two most popular open-source BaaS platforms to replace Firebase without depending on a proprietary cloud. Both deploy with Docker on a VPS, but their architectures, resource requirements, and ideal use cases differ significantly. This guide compares both platforms point by point to help you choose the right one for your project — and your server.

14 min read8 steps
Contents· What is a BaaS and why self-host it?1/14
  1. 01What is a BaaS and why self-host it?
  2. 02Supabase vs Appwrite — 12-criteria comparison
  3. 03Deploying Supabase on a VPS
  4. 04Deploying Appwrite on a VPS
  5. 05Authentication — Provider Comparison and OAuth
  6. 06Serverless Functions — Deno vs 30+ Runtimes
  7. 07Real-Time and File Storage
  8. 08Appwrite: console unreachable on first launch — give it time
  9. 09Supabase: 502 Bad Gateway from gateway on startup — normal behavior
  10. 10Appwrite 2.0: migrating from 1.x — procedure and breaking changes
  11. 11Supabase 0.8.0: Kong to Envoy — impact and TLS migration
  12. 12Decision guide — Supabase or Appwrite for your project?
  13. 13Common errors and fixes — both platforms
  14. 14Conclusion: two excellent BaaS platforms, two different philosophies

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

Scroll the table

CriterionSupabaseAppwrite
DatabasePostgreSQLPostgreSQL by default since 2.0 (MariaDB and MongoDB available)
Minimum RAM4 GB4 GB (+ 2 GB swap)
Recommended production RAM8 GB or moreNot published (4 GB minimum)
Number of containers~11 (13 with Logflare and Vector)~18
Main port8000 (Envoy since 0.8.0, Kong before)80 / 443 (Traefik)
Admin port8000 (Studio via the gateway, basic auth)80 / console (Traefik)
Included servicesAuth, PostgREST, Realtime, Storage, Edge Functions, StudioAuth, Databases, Storage, Functions, Messaging, Realtime
Auth providers15+30+
Functions runtimeDeno only30+ runtimes (Node, Python, PHP, Go, Dart, Ruby, Bun…)
Client SDKsJS, Python, Swift, Kotlin, Flutter, C#JS, iOS, Android, Flutter, React Native, Web
RealtimeWebSocket via Realtime serviceWebSocket via Appwrite Realtime
LicenseApache 2.0BSD 3-Clause

Deploying Supabase on a VPS

  1. Step 1 — Server prerequisites

    Provision a VPS with at least 4 GB of RAM (8 GB recommended for production), Docker and Docker Compose installed. Do not expose the gateway's port 8000, which serves both the API and Studio, over plain HTTP on the Internet: put an HTTPS reverse proxy (Caddy or Nginx) in front on port 443 and publish the gateway on loopback (API_GW_HTTP_PORT=127.0.0.1:8000 in .env), since Docker bypasses ufw rules. The Supavisor pooler also publishes ports 5432 and 6543: if you need no external connections, prefix them with 127.0.0.1: in docker-compose.yml. A minimum 40 GB SSD disk is recommended for PostgreSQL.

  2. Step 2 — Clone the repository and configure the environment

    Clone with git clone --depth 1 https://github.com/supabase/supabase, copy the contents of supabase/docker into a project folder and copy .env.example to .env. Never start with the example values: generate secrets and keys with sh utils/generate-keys.sh then sh utils/add-new-auth-keys.sh, and check at minimum POSTGRES_PASSWORD, JWT_SECRET (at least 32 characters), ANON_KEY, SERVICE_ROLE_KEY, DASHBOARD_PASSWORD (Studio access) and the public URLs (SUPABASE_PUBLIC_URL, API_EXTERNAL_URL, SITE_URL).

  3. Step 3 — Start the stack

    Run docker compose up -d (or sh run.sh start, equivalent to docker compose up -d --wait). With Supabase 0.8.0+, Envoy (not Kong) serves port 8000. Check status with docker compose ps and wait until all containers are healthy.

  4. Step 4 — Verify the installation

    Access Studio through the gateway at http://your-ip:8000 (or your HTTPS domain behind the reverse proxy), with the DASHBOARD_USERNAME login and DASHBOARD_PASSWORD password. Test a simple API call with curl http://your-ip:8000/functions/v1/hello -H "apikey: YOUR_PUBLISHABLE_KEY": the sample function's response confirms the gateway routes requests correctly.

Deploying Appwrite on a VPS

  1. Step 1 — Server prerequisites

    Appwrite requires at least 2 CPU cores, 4 GB of RAM and 2 GB of swap. Its ~18 containers (default setup) include Traefik as a reverse proxy. Ports 80 and 443 must be open.

  2. Step 2 — Run the interactive installer

    Run docker run -it --rm --publish 20080:20080 --volume /var/run/docker.sock:/var/run/docker.sock --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw --entrypoint="install" appwrite/appwrite:2.7.1, pinning the released version rather than latest. The wizard opens in your browser on port 20080: it asks for your domain, generates the keys and a tailored docker-compose.yml, and creates the admin account. Close port 20080 once installation is done.

  3. Step 3 — Wait for startup to finish

    On first startup, the containers may take a few minutes to become operational, and the console may answer with an error in the meantime. Follow progress with docker compose ps and docker compose logs -f appwrite. Migrations only apply when upgrading an existing instance, and are run manually with docker compose exec appwrite migrate.

  4. Step 4 — Sign in to the console

    Once installation is complete, open your domain (or the server IP) in the browser, sign in to the console with the admin account created by the wizard, then create your first project.

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 Supabase Auth (formerly GoTrue) as its authentication service — a lightweight daemon written in Go. Appwrite integrates its own Auth service configurable per project from the web console.

Important post-2.0 note: issue #13547 (https://github.com/appwrite/appwrite/issues/13547), opened in September 2026, reported that password reset and email invitations did not work on Appwrite 2.0 self-hosted deployments. It was closed without a named fix release, as the team could not reproduce it. Test these flows in a staging environment before migrating your production instance.

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.

Appwrite 2.1.0 note: the _APP_LOGGING_PROVIDER and _APP_LOGGING_CONFIG_REALTIME environment variables are no longer read, and error logging goes through _APP_LOGGING_CONFIG alone, which now only accepts a Sentry DSN: a LogOwl, Raygun or AppSignal DSN is rejected at startup. Remove the old variables from your .env and check that DSN before upgrading.

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.

A note with Supabase: the Realtime service sometimes starts before PostgreSQL is fully ready, generating the error could not connect to the database. Restarting the realtime container usually resolves this.

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: console unreachable on first launch — give it time

If the Appwrite console shows an error or remains inaccessible in the first few minutes, do not blindly restart the containers: first startup can take a few minutes. Follow progress with docker compose ps and docker compose logs -f appwrite, and wait until all containers run without errors. During an upgrade, however, nothing migrates on its own: after backing up your data, run docker compose exec appwrite migrate and let it finish without stopping the containers.

Supabase: 502 Bad Gateway from gateway on startup — normal behavior

The Supabase API gateway (Kong up to 0.7.x, Envoy from 0.8.0) may return 502 errors during the first few tens of seconds after docker compose up -d. This is normal and transient — the gateway waits for PostgREST, GoTrue and other services to be ready. Wait until docker compose ps shows all containers as healthy. If 502s persist beyond a few minutes, inspect logs with docker compose logs rest and docker compose logs api-gw (the service was named kong before 0.8.0).

Appwrite 2.0: migrating from 1.x — procedure and breaking changes

Appwrite 2.0 was announced for self-hosting on September 7, 2026 (source: https://appwrite.io/changelog/entry/2026-09-07). It is a major update: PostgreSQL becomes the default database for new installs, with MariaDB and MongoDB still offered. An existing MariaDB instance stays on MariaDB after the upgrade: 2.0 does not convert your data to PostgreSQL.

Mandatory migration path. An instance older than 1.9.6 must first be upgraded to 1.9.6 (from 1.8.x, via 1.9.5 and its migration); from 1.9.6 onward, upgrading to the latest 2.x is direct. Official procedure:

1. Back up all your data: docker compose down, then copy the appwrite directory (docker-compose.yml, .env) and the named Docker volumes holding the database and files.
2. If needed, first upgrade to 1.9.6: from the parent of the appwrite directory, rerun the install command with --entrypoint="upgrade" and the appwrite/appwrite:1.9.6 image.
3. From the appwrite directory, run the migration: docker compose exec appwrite migrate.
4. Upgrade to 2.x: rerun the upgrade command with the latest released image (appwrite/appwrite:2.7.1 in November 2026).
5. Run docker compose exec appwrite migrate again — do not stop containers during this process — then check with docker ps | grep appwrite/appwrite that all containers run the same version.

Breaking changes. Issue #13547, closed in September 2026 without a named fix, reported broken password reset and email invitations in Appwrite 2.0 self-hosted. Test these flows in pre-production before migrating your main instance. In 2.1.0, _APP_LOGGING_PROVIDER and _APP_LOGGING_CONFIG_REALTIME are no longer read and _APP_LOGGING_CONFIG only accepts a Sentry DSN — remove the former and check the latter before upgrading. No rollback procedure is documented: only a full restore from backup lets you return to 1.x.

Supabase 0.8.0: Kong to Envoy — impact and TLS migration

Supabase docker-compose 0.8.0, released August 11, 2026 (source: https://github.com/supabase/supabase/blob/master/docker/CHANGELOG.md), replaces Kong with Envoy as the default API gateway (Kong remains available as an opt-in, with sh run.sh config add kong). This architectural change is transparent for most deployments, but carries a TLS breaking change: the TLS listener on port 8443 disappears.

What changes concretely. If your reverse proxy or health check scripts made direct HTTPS requests to https://your-ip:8443, those calls will fail after the update. Envoy does not re-expose this port. TLS termination must now be handled exclusively by your front-end reverse proxy.

Migration steps. Before upgrading to 0.8.0:
- Audit all references to port 8443 in your deployment scripts, health checks, and firewall rules.
- Replace them with calls to port 8000 over HTTP from the internal network, with TLS terminated by the reverse proxy.
- Upgrade with the official procedure (sh update.sh, then sh run.sh pull && sh run.sh recreate): a plain docker compose pull is not enough, since docker-compose.yml itself changes. Then check that docker compose ps shows the api-gw service (container supabase-envoy), which replaces the kong service, as healthy.

In .env, KONG_HTTP_PORT is still read as a fallback for the new API_GW_HTTP_PORT variable, and KONG_HTTPS_PORT only serves the Kong option: you can switch to API_GW_HTTP_PORT to clarify your configuration.

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, you are at the documented minimum of both platforms (4 GB for Supabase, 4 GB plus 2 GB of swap for Appwrite); Supabase recommends 8 GB or more in production.

In 2026, both platforms are evolving rapidly. Appwrite 2.0 makes PostgreSQL its default database for new installs — reducing Supabase's historical advantage on that point — while Supabase modernizes its gateway with Envoy. For a new installation, both are equivalent on the database question. For an existing installation (which stays on MariaDB on the Appwrite side), plan a maintenance window and test critical flows before any major update.

Common errors and fixes — both platforms

  • Supabase — 502 Bad Gateway (gateway): wait for all services to be healthy. If persistent: docker compose restart api-gw (0.8.0+) or docker compose restart kong (< 0.8.0).
  • Supabase — Realtime could not connect to the database: restart with docker compose restart realtime.
  • Supabase — Invalid JWT: check that ANON_KEY and SERVICE_ROLE_KEY are signed with the same JWT_SECRET as in .env.
  • Supabase 0.8.0 — port 8443 unreachable: the Kong TLS listener was removed with Envoy. Remove direct calls to port 8443 and delegate TLS to the front-end reverse proxy.
  • Appwrite — console unreachable on startup: first startup can take a few minutes. Check docker compose ps and the logs before restarting anything.
  • Appwrite — docker compose down -v: DANGER — deletes all data volumes. Never run in production.
  • Appwrite — function timeout: cold start of an unused runtime may exceed the default timeout. Increase the limit in the function settings (Settings > Timeout, 900 s maximum).
  • Appwrite 2.x — migration blocked: an instance older than 1.9.6 must first go through 1.9.6, running docker compose exec appwrite migrate at each step. Skipping this step risks a failed migration: restore your backup and start over.
  • Appwrite 2.0 — password reset / invitations: issue #13547 reported in self-hosted, closed without a named fix. Test these flows before going to production.
  • Appwrite 2.1.0 — dropped variables: _APP_LOGGING_PROVIDER and _APP_LOGGING_CONFIG_REALTIME are no longer read; remove them from .env, and keep only a Sentry DSN in _APP_LOGGING_CONFIG, the only one accepted at startup.

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 the richness of its function runtimes, and the quality of its mobile SDKs.

Both platforms went through structural updates in 2026: Appwrite 2.0 (September 2026) makes PostgreSQL the default database for new installs, Supabase 0.8.0 (August 2026) switches from Kong to Envoy. Plan your migrations with a full backup, a test environment, and validation of critical flows — especially email authentication for Appwrite 2.0. In both cases, a dedicated VPS with at least 4 GB of RAM and automated volume backups is the foundation of a reliable deployment. Starting from 99 DH/month on ServOrbit.

Host your BaaS on a VPS you control

Whether you choose Supabase or Appwrite, both deserve a stable, fast, and backed-up VPS. Our Cloud VPS plans start at 4 GB RAM with on-demand snapshots — exactly what you need to run your open-source backend in production.