Loading post...
An engineering-first analysis of BaaS platforms: when to choose Firebase, when to choose Supabase, and why it matters for your stack
rayanstudio
Choosing a BaaS isn't about features. It's about architectural philosophy.
Database Architecture
Firebase: NoSQL document database (Firestore) Supabase: PostgreSQL with real-time capabilities
This single choice cascades through your entire architecture.
// Denormalized structure
const userDoc = {
id: 'user123',
name: 'Alice',
email: 'alice@example.com',
posts: {
post1: { title: 'First Post', likes: 10 },
post2: { title: 'Second Post', likes: 5 },
},
followers: ['user456', 'user789'],
}
// Reading is fast, writing duplicates data-- Normalized relational structure
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
);
CREATE TABLE posts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id),
title TEXT NOT NULL,
likes INTEGER DEFAULT 0
);
CREATE TABLE followers (
user_id UUID REFERENCES users(id),
follower_id UUID REFERENCES users(id),
PRIMARY KEY (user_id, follower_id)
);Trade-offs:
Firebase:
Supabase:
import { onSnapshot, collection } from 'firebase/firestore'
const unsubscribe = onSnapshot(collection(db, 'messages'), (snapshot) => {
const messages = snapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}))
setMessages(messages)
})How it works: WebSocket connection to Firebase servers, push-based updates.
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(url, key)
const subscription = supabase
.channel('messages')
.on(
'postgres_changes',
{ event: '*', schema: 'public', table: 'messages' },
(payload) => {
console.log('Change received!', payload)
},
)
.subscribe()How it works: PostgreSQL logical replication + Phoenix channels. Any database change is broadcast