Supabase vs Appwrite in 2026: Which Open Source BaaS?
Supabase vs Appwrite in 2026: Open Source BaaS Platforms Compared
TL;DR
Both Supabase and Appwrite are open source Firebase replacements with auth, database, storage, and real-time built in. Supabase is built on PostgreSQL — full SQL access, row-level security, vector search, and the largest open source BaaS community. Appwrite is database-agnostic with a document model and 14 function runtimes — more opinionated, but more flexible about language choice for server-side logic. For most developers: Supabase wins on database power and ecosystem. For teams running multi-language functions or preferring a document model: Appwrite makes a strong case.
Key Takeaways
- Supabase (Apache-2.0, 76K+ stars) is built on PostgreSQL — full SQL, RLS, PostgREST auto-API, pgvector, and database branching
- Appwrite (BSD-3-Clause, 46K+ stars) uses a document model on MariaDB with 14 function runtimes (Node.js, Python, PHP, Ruby, Go, Swift, Dart, Bun, Deno, and more)
- Firebase's Blaze plan costs $0.05/GB/month storage + $0.12/GB bandwidth — a growing app pays $200-500+/month
- Supabase's real-time uses PostgreSQL logical replication (truly database-driven); Appwrite's real-time is event-based through the application layer
- Appwrite has 12+ client SDKs including more mobile platform SDKs; Supabase has JS, Flutter, Swift, Kotlin, Python
- Both support 30+ OAuth providers, email/password auth, magic links, and anonymous sessions
The Firebase Replacement Problem
Firebase's problem isn't the product — it's the pricing trajectory. The free Spark plan is genuinely useful, which creates adoption. Then as an app grows, costs become unpredictable: storage at $0.05/GB/month, Firestore reads at $0.06/100K, writes at $0.18/100K, bandwidth at $0.12/GB. A mobile app with 50K daily active users doing moderate database activity can easily hit $300-600/month.
Self-hosted BaaS eliminates per-operation pricing. One VPS costs the same whether you do 1 million or 100 million database reads.
The more interesting question is which self-hosted BaaS fits your architecture.
Supabase — PostgreSQL-Powered BaaS
Supabase makes a bold architectural bet: PostgreSQL is a better foundation for a modern BaaS than Firestore, MongoDB, or DynamoDB. The bet has paid off — Supabase's 76K GitHub stars and significant cloud ARR validate the approach.
The core insight is that PostgreSQL is already a complete platform: full ACID transactions, row-level security, stored procedures, triggers, extensions, full-text search, JSON support, and a rich ecosystem of tools. Supabase builds a developer-friendly layer on top rather than replacing the database.
# Supabase self-hosted (key services)
services:
db:
image: supabase/postgres:15.1.0.147
environment:
POSTGRES_PASSWORD: your-db-password
volumes:
- supabase_db:/var/lib/postgresql/data
rest:
image: postgrest/postgrest:v12.0.2
environment:
PGRST_DB_URI: postgres://authenticator:password@db:5432/postgres
PGRST_JWT_SECRET: your-jwt-secret
PGRST_DB_SCHEMAS: public,storage,extensions
auth:
image: supabase/gotrue:v2.140.0
environment:
GOTRUE_SITE_URL: https://app.yourdomain.com
GOTRUE_JWT_SECRET: your-jwt-secret
DATABASE_URL: postgres://supabase_auth_admin:password@db:5432/postgres
GOTRUE_SMTP_HOST: smtp.yourdomain.com
realtime:
image: supabase/realtime:v2.27.5
environment:
DB_HOST: db
DB_PASSWORD: your-db-password
JWT_SECRET: your-jwt-secret
storage:
image: supabase/storage-api:v0.46.4
environment:
PGSQL_CONNECTION_STRING: postgres://supabase_storage_admin:password@db:5432/postgres
studio:
image: supabase/studio:20240101-8e4a94c
ports:
- "3000:3000"
environment:
SUPABASE_URL: http://kong:8000
SUPABASE_ANON_KEY: your-anon-key
volumes:
supabase_db:
Row-level security is Supabase's security model — define access rules at the database level using PostgreSQL policies:
-- Enable RLS on the table
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
-- Users can only read their own posts and all published posts
CREATE POLICY "Read own or published posts"
ON posts FOR SELECT
USING (
auth.uid() = user_id -- Own posts
OR published = true -- Or any published post
);
-- Only the author can update their posts
CREATE POLICY "Authors can update own posts"
ON posts FOR UPDATE
USING (auth.uid() = user_id);
-- Check user role for admin access
CREATE POLICY "Admins can read everything"
ON posts FOR SELECT
USING (
(SELECT role FROM user_profiles WHERE id = auth.uid()) = 'admin'
);
The Supabase JavaScript SDK is arguably the best-designed BaaS SDK available:
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
'https://db.yourdomain.com',
'your-anon-key'
);
// Type-safe queries (with TypeScript generated types)
const { data: posts, error } = await supabase
.from('posts')
.select(`
id, title, content, created_at,
author:users!inner(id, name, avatar_url),
tags:post_tags(tag:tags(name))
`)
.eq('published', true)
.order('created_at', { ascending: false })
.limit(20);
// Real-time subscription (WebSocket)
const channel = supabase
.channel('posts-changes')
.on('postgres_changes', {
event: 'INSERT',
schema: 'public',
table: 'posts',
filter: 'published=eq.true',
}, (payload) => {
console.log('New post published:', payload.new);
})
.subscribe();
// File upload
const { data, error: uploadError } = await supabase.storage
.from('avatars')
.upload(`${userId}/avatar.png`, file, {
contentType: 'image/png',
upsert: true,
});
Key features:
- PostgreSQL with full SQL access
- Auto-generated REST API (PostgREST) from your database schema
- Row-level security (database-enforced access control)
- Real-time via PostgreSQL logical replication
- Auth: email/password, magic links, phone OTP, 50+ OAuth providers, SSO/SAML
- File storage (S3-compatible)
- Edge functions (Deno/TypeScript)
- Vector search (pgvector)
- Database branching for dev/staging
- PostgreSQL extensions (PostGIS, pg_cron, pg_partman, TimescaleDB)
- SDKs: JavaScript/TypeScript, Flutter, Swift, Kotlin, Python, C#, Go
- Apache-2.0 license, 76K+ stars
Appwrite — The Multi-Runtime BaaS
Appwrite's architecture makes different tradeoffs: it abstracts the database behind a document API (no direct SQL), but provides far more flexibility in serverless function runtimes. If your team writes backend logic in Python, Ruby, or Swift — not just Node.js and TypeScript — Appwrite's 14 runtimes are a meaningful advantage.
# Appwrite Docker Compose (simplified)
services:
appwrite:
image: appwrite/appwrite:1.5.7
restart: unless-stopped
ports:
- "80:80"
- "443:443"
environment:
- _APP_ENV=production
- _APP_LOCALE=en
- _APP_DOMAIN=api.yourdomain.com
- _APP_DOMAIN_TARGET=api.yourdomain.com
- _APP_DB_HOST=appwrite-mariadb
- _APP_DB_PORT=3306
- _APP_DB_SCHEMA=appwrite
- _APP_DB_USER=appwrite
- _APP_DB_PASS=password
- _APP_REDIS_HOST=appwrite-redis
- _APP_SMTP_HOST=smtp.yourdomain.com
- _APP_SMTP_PORT=587
- _APP_OPENSSL_KEY_V1=your-encryption-key
- _APP_JWT_SECRET=your-jwt-secret
depends_on:
- appwrite-mariadb
- appwrite-redis
appwrite-worker-functions:
image: appwrite/appwrite:1.5.7
entrypoint: worker-functions
appwrite-executor:
image: openruntimes/executor:0.5.5
# Executes serverless functions in Docker containers
appwrite-mariadb:
image: mariadb:10.11
volumes:
- appwrite_mariadb:/var/lib/mysql
appwrite-redis:
image: redis:7.2-alpine
volumes:
- appwrite_redis:/data
volumes:
appwrite_mariadb:
appwrite_redis:
The document model organizes data as collections of documents with typed attributes (string, integer, float, boolean, enum, array, relationship). This is similar to Firebase Firestore — flexible schema, no migrations required for adding fields.
import { Client, Databases, ID } from 'appwrite';
const client = new Client()
.setEndpoint('https://api.yourdomain.com/v1')
.setProject('your-project-id');
const databases = new Databases(client);
// Create a document
const post = await databases.createDocument(
'main-db', // Database ID
'posts', // Collection ID
ID.unique(), // Document ID
{
title: 'Hello from Appwrite',
content: 'This is my post content.',
published: true,
authorId: currentUser.$id,
}
);
// Query documents
const posts = await databases.listDocuments('main-db', 'posts', [
Query.equal('published', true),
Query.orderDesc('$createdAt'),
Query.limit(20),
]);
Serverless functions run in isolated Docker containers with 14 available runtimes:
// Appwrite Function (Node.js runtime)
export default async ({ req, res, log, error }) => {
const { userId } = JSON.parse(req.body);
// Access other Appwrite services from inside a function
const client = new Client()
.setEndpoint(process.env.APPWRITE_ENDPOINT)
.setProject(process.env.APPWRITE_PROJECT_ID)
.setKey(process.env.APPWRITE_API_KEY);
const databases = new Databases(client);
const user = await databases.getDocument('users-db', 'profiles', userId);
log(`Processing user: ${user.name}`);
return res.json({ user, processed: true });
};
Available function runtimes: Node.js, Python, PHP, Ruby, Go, Swift, Dart, Bun, Deno, .NET, Kotlin, Java
Key features:
- Document model (no direct SQL, flexible schema)
- 14 function runtimes
- Auth: email/password, OAuth2, phone/SMS, anonymous, JWT, magic links
- 30+ OAuth providers
- File storage with image transformation API
- Real-time subscriptions (WebSocket)
- Teams and permission management
- Webhooks for all events
- SDKs: 12+ platforms (Web, Flutter, Android, iOS, React Native, Node.js, Python, PHP, Ruby, Go, .NET, Swift)
- Rate limiting and abuse protection
- BSD-3-Clause license, 46K+ stars
Side-by-Side Comparison
| Feature | Supabase | Appwrite |
|---|---|---|
| License | Apache-2.0 | BSD-3-Clause |
| Stars | 76K+ | 46K+ |
| Database model | PostgreSQL (relational) | Document (MariaDB backend) |
| Direct SQL | ✅ Full PostgreSQL | ❌ |
| Row-level security | ✅ PostgreSQL RLS | Collection-level permissions |
| Real-time | Postgres logical replication | Event-based WebSocket |
| Edge functions | Deno (TypeScript) | 14 runtimes |
| Vector search | ✅ pgvector | ❌ |
| Database branching | ✅ | ❌ |
| SDK platforms | JS, Flutter, Swift, Kotlin, Python | 12+ platforms including React Native |
| OAuth providers | 50+ | 30+ |
| Min RAM (self-hosted) | 2 GB | 4 GB |
| Number of services | 8+ | 12+ |
Decision Framework
Choose Supabase if:
- PostgreSQL's power is important — complex queries, JOINs, stored procedures, extensions
- Row-level security (database-enforced access control) is a requirement
- Vector search for AI/semantic features is on the roadmap
- JavaScript/TypeScript is your primary development language
- Database branching for dev/staging workflows is valuable
- You want the largest BaaS community and ecosystem
Choose Appwrite if:
- You need serverless functions in non-JavaScript languages (Python, Go, Ruby, PHP, Swift)
- A document model (schemaless, no migrations) fits your mental model better than relational
- You're building cross-platform apps with React Native or need the full SDK breadth
- You want a more traditional BaaS experience similar to Firebase Firestore
- BSD-3-Clause license is preferred over Apache-2.0
Cost Comparison
| Scale | Firebase Blaze | Supabase Self-Hosted | Appwrite Self-Hosted |
|---|---|---|---|
| 1K MAU | ~$0 | $20–30/month | $20–30/month |
| 10K MAU | ~$50/month | $20–30/month | $30–40/month |
| 100K MAU | $200+/month | $40–80/month | $50–100/month |
PostgreSQL as a Foundation: Why It Matters
Supabase's most distinctive architectural decision is using PostgreSQL directly rather than abstracting it behind a custom data layer. This deserves more examination than a simple "it uses Postgres" observation.
PostgreSQL is the most feature-complete open source relational database in existence. It handles ACID transactions, complex JOINs across dozens of tables, stored procedures, triggers, full-text search, JSON and JSONB document storage, geospatial data via PostGIS, time-series data via TimescaleDB, vector similarity search via pgvector, and an extension ecosystem covering hundreds of use cases. These are not hypothetical features — they are things that production applications need and use.
When Supabase gives you direct SQL access, it means you can use all of these capabilities without negotiating with an API layer. Need to run a complex analytics query across three tables with aggregates? Write the SQL. Need to implement a background job with pg_cron? Go ahead. Need to add vector search for semantic similarity? Enable the pgvector extension. The full power of one of the world's best databases is available without any API mediation.
Appwrite's document model makes a different tradeoff. By abstracting the database behind a document API, Appwrite provides a more consistent developer experience across different team compositions and makes the schema more flexible. Adding a new field to a collection does not require a migration. The tradeoff is that complex queries must be expressed in Appwrite's query API rather than SQL — which is generally fine for straightforward use cases but constraining for complex data access patterns.
Choosing Based on Your Application's Data Model
The right choice between Supabase and Appwrite often comes down to your application's data model and query patterns.
Applications with strong relational data — users who belong to organizations, organizations that have projects, projects that have tasks with assignees — benefit from Supabase's PostgreSQL foundation. These relationships are natural in SQL: foreign keys, JOINs, and cascading operations work exactly as you would expect. Row-level security policies let you express complex multi-tenant access rules (a user can read rows in the projects table where they have a membership, or where the project is public) at the database level, enforced before data leaves the database.
Applications with more document-like data — flexible metadata, user-generated content with variable structure, mobile app data with offline sync requirements — may find Appwrite's document model more natural. You can add new fields to documents without schema migrations, and the flexibility suits use cases where the data structure is not fully known in advance.
For applications that need heavy serverless function logic — data processing pipelines, webhook handlers, scheduled jobs — Appwrite's 14 function runtimes become a meaningful advantage. If your team has Python data engineers alongside JavaScript frontend developers, Appwrite's ability to run functions in both languages from the same platform is genuinely useful. Supabase's edge functions are TypeScript-only (Deno runtime), which covers most needs but leaves language diversity to other parts of the stack.
Both platforms run well in self-hosted configurations. The how-to-migrate-from-firebase-to-appwrite guide covers the Appwrite deployment and migration process in detail. For teams starting fresh and evaluating the full BaaS landscape including lighter-weight options, the comparison covers the spectrum from heavyweight (Supabase) to middleweight (Appwrite) to ultralight (PocketBase).
Self-Hosting Considerations
Both Supabase and Appwrite are designed to run self-hosted, but the operational experience differs.
Supabase's self-hosted deployment involves eight or more Docker containers: the PostgreSQL database, PostgREST API layer, GoTrue auth service, Realtime server, Storage API, Edge Functions runtime, Supavisor connection pooler, and Studio (the admin UI). These are all well-documented and the official docker-compose configuration works reliably, but it is a non-trivial number of services to manage. Minimum practical RAM for self-hosted Supabase is around 2 GB; 4 GB is more comfortable for a real application.
Appwrite's self-hosted deployment is similarly complex: the main application container, worker containers for different job types, the executor for running functions, MariaDB, Redis, and the InfluxDB and Telegraf containers for metrics. Appwrite requires more RAM at minimum (approximately 4 GB) but the Docker Compose configuration is also well-maintained.
Both platforms benefit from a reverse proxy layer (Caddy or Nginx) and a managed PostgreSQL/MariaDB backup strategy. For teams running these on a PaaS like Coolify or CapRover, both platforms deploy from Docker Compose, which makes management and backup straightforward.
Cost at scale is similar for both. A VPS with 4–8 GB RAM at $7–15/month handles a typical self-hosted BaaS deployment. At high usage levels, you may need to scale the database independently, but the fundamental economics — self-hosted infrastructure at predictable cost versus Firebase's per-operation pricing — hold regardless of which BaaS you choose. Database backup automation is critical for both: PostgreSQL dumps for Supabase and MariaDB dumps for Appwrite should run nightly to separate offsite storage, separate from the VPS where the application runs.
Related: Best Open Source BaaS Platforms 2026 · Appwrite vs PocketBase · PocketBase vs Supabase
See open source alternatives to Supabase on OSSAlt.