Skip to main content
LadeStack LogoLadeStack
Backend as a Service 8 min read August 12, 2024

BaaS Platforms Compared: Architectural Evaluation of Firebase, Supabase, and Appwrite

An objective, in-depth architectural comparison of Firebase, Supabase, and Appwrite covering data models, security paradigms, real-time protocols, edge functions, self-hosting viability, and vendor lock-in tradeoffs.

Architectural comparison of Firebase, Supabase, and Appwrite

Introduction: The Evolution of Backend-as-a-Service

Backend-as-a-Service (BaaS) platforms have transformed from simple mobile database helpers into comprehensive application foundations. By abstracting routine infrastructure—such as identity management, database hosting, client-side authorization, binary storage, and serverless compute—BaaS platforms allow product engineering teams to focus on customer-facing differentiation.

However, selecting a BaaS engine is a foundational architectural commitment. Migrating away from a poorly chosen platform later involves substantial refactoring of client code, authorization logic, and data schemas. Today, the three dominant options represent markedly different architectural philosophies:

  1. Google Firebase: The pioneer of managed cloud BaaS, tightly coupled to Google Cloud Platform’s proprietary serverless ecosystem.
  2. Supabase: The “open-source Firebase alternative,” built directly atop PostgreSQL, leveraging relational standards and open-source tooling.
  3. Appwrite: A self-hostable, container-first BaaS platform engineered for modularity, language-agnostic SDKs, and complete infrastructure ownership.

This guide provides an objective, code-level architectural comparison across six critical dimensions: data modeling, authorization, real-time mechanics, serverless functions, developer experience, and lock-in risk.


1. Architectural Overview & Platform Philosophies

┌─────────────────────────────────────────────────────────────────────────────┐
│                             BAAS LANDSCAPE                                  │
├─────────────────────┬───────────────────────────┬───────────────────────────┤
│   Google Firebase   │         Supabase          │         Appwrite          │
├─────────────────────┼───────────────────────────┼───────────────────────────┤
│ • Proprietary Cloud │ • Open-Source Core        │ • Open-Source Core        │
│ • NoSQL Document    │ • PostgreSQL Relational   │ • Document / Key-Value    │
│ • Fully Managed     │ • Cloud & Self-Hostable   │ • Self-Hostable & Cloud   │
│ • GCP Ecosystem     │ • SQL & Extensions (pg_*) │ • Docker Container-First  │
└─────────────────────┴───────────────────────────┴───────────────────────────┘

Firebase: The Fully Managed Cloud Ecosystem

Firebase operates as a curated wrapper over Google Cloud infrastructure. It prioritizes zero-ops scalability: you do not configure servers, allocate connection pools, or scale disks. In exchange, its underlying databases (Cloud Firestore and Firebase Realtime Database) are proprietary closed-source systems.

Supabase: Relational Rigor on Open-Source PostgreSQL

Supabase rejects proprietary storage engines. Every Supabase project is a full, dedicated PostgreSQL database with superuser-like capabilities, pre-configured with PostgREST for instant auto-generated REST APIs, GoTrue for authentication, and Realtime for WebSocket broadcasting. If you know SQL, you already know Supabase.

Appwrite: Containerized Modularity & Self-Hosting

Appwrite is designed from the ground up to run anywhere Docker runs. It packages authentication, database management, file storage, and serverless runtimes into a unified microservices suite orchestrated via Docker Compose. It treats self-hosting as a first-class citizen, making it attractive for privacy-conscious teams subject to strict data-residency laws.


2. Core Data Models & Query Capabilities

The single most impactful architectural difference among these three platforms lies in how data is structured and queried:

Dimension Firebase (Firestore) Supabase Appwrite
Underlying Engine Cloud Firestore (NoSQL) PostgreSQL (Relational) MariaDB / Redis / Custom
Data Structure Collections & Documents Tables, Rows, Relations Databases, Collections, Documents
Join Support None (Requires Denormalization) Full Relational SQL (JOIN) Internal Relationships
Indexing Automatic composite indexes Full PostgreSQL B-Tree, GIN, GiST Manual database indexes
Query Flexibility Limited range filtering Arbitrary SQL, CTEs, Aggregates Structured Query API (Query.equal)

Querying Patterns in Practice

Firestore (NoSQL Document Lookup)

Firestore queries must follow strict index rules. You cannot execute inequality filters on multiple distinct fields in a single query:

import { collection, query, where, getDocs } from 'firebase/firestore';

// Requires an explicit composite index created in Firebase Console
const q = query(
  collection(db, 'invoices'),
  where('tenantId', '==', 'tenant_123'),
  where('status', '==', 'unpaid')
);

const snapshot = await getDocs(q);
const invoices = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));

Supabase (Relational SQL & PostgREST Client)

Supabase provides the full expressive power of relational queries, including nested relational joins in a single round-trip:

import { supabase } from './supabaseClient';

// Relational join: fetch tenant invoices along with client contact details
const { data, error } = await supabase
  .from('invoices')
  .select(`
    id,
    amount_cents,
    status,
    customers (
      name,
      email
    )
  `)
  .eq('tenant_id', 'tenant_123')
  .eq('status', 'unpaid');

Appwrite (Structured Document Query Engine)

Appwrite uses a programmatic Query builder mapped over document collections:

import { Client, Databases, Query } from 'appwrite';

const databases = new Databases(client);

const response = await databases.listDocuments(
  'production_db',
  'invoices_col',
  [
    Query.equal('tenantId', 'tenant_123'),
    Query.equal('status', 'unpaid'),
    Query.limit(50)
  ]
);

3. Security & Access Control Paradigms

Because client applications frequently communicate directly with the BaaS database, authorization rules are your primary security boundary.

Firebase: Declarative Security Rules

Firestore uses a domain-specific language (DSL) evaluated on Google’s edge:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /invoices/{invoiceId} {
      // Enforce tenant isolation via auth token claims
      allow read, write: if request.auth != null 
        && request.auth.token.tenant_id == resource.data.tenantId;
    }
  }
}

Tradeoff: As rules become complex (e.g., checking role hierarchies across related documents), rule files become difficult to test, debug, and maintain.

Supabase: PostgreSQL Row-Level Security (RLS)

Supabase delegates authorization directly to PostgreSQL’s native engine:

-- Enable native Row Level Security
ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;

-- Enforce tenant isolation using JWT session context
CREATE POLICY tenant_isolation_policy ON invoices
  FOR ALL
  USING (
    tenant_id = (auth.jwt() -> 'app_metadata' ->> 'tenant_id')::uuid
  );

Advantage: Rules are standard PostgreSQL policies. They apply uniformly whether queries originate from client SDKs, backend microservices, or direct psql connections.

Appwrite: Permission Strings and Role Arrays

Appwrite implements an intuitive permission array model attached to documents:

import { Permission, Role } from 'appwrite';

await databases.createDocument(
  'production_db',
  'invoices_col',
  'unique()',
  { tenantId: 'tenant_123', amount: 5000 },
  [
    Permission.read(Role.team('team_123', 'admin')),
    Permission.update(Role.team('team_123', 'finance')),
    Permission.delete(Role.team('team_123', 'owner')),
  ]
);

Advantage: Simple to understand and configure programmatically directly within application flows.


4. Real-Time Data Synchronization Architecture

Each platform employs a distinct transport and change-detection protocol for pushing data to clients:

[Firebase] Client ◄──── Proprietary Persistent Stream ────► [Firestore Engine]
[Supabase] Client ◄──── WebSocket (wal2json / pgoutput) ───► [PostgreSQL WAL Engine]
[Appwrite] Client ◄──── WebSocket (Redis Pub/Sub) ─────────► [Appwrite Realtime Gateway]
  1. Firebase: Deeply optimized snapshot listeners. When a document changes, the Firestore engine computes client-side delta diffs and streams them over a persistent bidirectional channel. It excels at low-latency mobile state synchronization.
  2. Supabase Realtime: Listens to PostgreSQL’s Write-Ahead Log (WAL) using the pgoutput logical decoding plugin. Changes committed in PostgreSQL are broadcast over Phoenix Channels (Elixir WebSockets) to subscribed client channels.
  3. Appwrite Realtime: Uses an internal Redis Pub/Sub cluster connected to WebSocket workers. Whenever an API mutation succeeds, an event is published across active subscriber sockets.

5. Serverless Compute & Edge Functions

No complex application can operate solely on database rules. Custom business logic (payment processing, image hashing, third-party API orchestration) requires serverless compute:

  • Firebase Cloud Functions: Runs on Google Cloud Functions (Node.js, Python). Tight integration with Firebase triggers (e.g., onDocumentWritten, onUserCreated). Cold starts can be noticeable in V1, though Cloud Functions V2 (Cloud Run based) improves concurrency.
  • Supabase Edge Functions: Powered by the Deno runtime distributed globally on the Supabase edge network. Sub-50ms cold starts, native TypeScript execution without build steps, and native web-standard APIs (fetch, Request, Response).
  • Appwrite Functions: Runs inside isolated Docker containers supporting more than 15 runtimes (Node.js, Python, PHP, Ruby, Dart, Go, Rust, Swift). Can be deployed with custom native system binaries.

6. Self-Hosting, Portability, and Vendor Lock-in

Criteria Google Firebase Supabase Appwrite
Self-Hosting Viability Impossible (Proprietary GCP) High (Official Docker Compose / K8s) First-Class (One-line Docker install)
Data Portability Export JSON documents via gcloud Standard pg_dump and psql MariaDB dump or Appwrite CLI export
Migration Exit Cost High: Rewriting schemas and rules Low: It is standard PostgreSQL Moderate: Standard document export
Offline Emulation Firebase Local Emulator Suite Supabase CLI (Local Dockerized Postgres) Local Appwrite Container Stack

If your organization must comply with strict data sovereignty regulations (e.g., healthcare HIPAA, EU GDPR on-premise mandates), Supabase or Appwrite are the viable choices. With Supabase, even if you leave the cloud platform, you retain a production-grade PostgreSQL database that can run on AWS RDS, Google Cloud SQL, or bare-metal servers with minimal changes.


7. Architectural Decision Matrix

                      Do you need a Relational Database
                           with SQL & Joins?
                                  │
                   ┌──────────────┴──────────────┐
                   │ YES                         │ NO
                   ▼                             ▼
           [Choose Supabase]          Is Self-Hosting a Hard
                                            Mandate?
                                                 │
                                  ┌──────────────┴──────────────┐
                                  │ YES                         │ NO
                                  ▼                             ▼
                          [Choose Appwrite]            [Choose Firebase]

Recommendation Guide

  • Choose Supabase if: You are building a complex SaaS application, financial system, or any product that inherently benefits from relational integrity, foreign keys, SQL views, and PostgreSQL extensions (such as pgvector for AI embeddings).
  • Choose Firebase if: You are developing a mobile-first app, game, or rapid prototype where zero infrastructure overhead is paramount, and your team wants seamless integration with Google Analytics, Crashlytics, and BigQuery.
  • Choose Appwrite if: You require full ownership of your data plane, intend to self-host on private cloud infrastructure, and value an intuitive, developer-friendly REST/WebSocket API over raw SQL management.

Conclusion & Further Reading

BaaS platforms are no longer toys for hackathons; they are production engines powering high-volume applications. By understanding their architectural tradeoffs early—specifically regarding data modeling and authorization boundaries—you avoid costly mid-lifecycle migrations.

More Engineering Articles