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 |
Related: Best Open Source BaaS Platforms 2026 · Appwrite vs PocketBase · PocketBase vs Supabase
See open source alternatives to Supabase on OSSAlt.