Skip to main content

Supabase Starter vs Firebase Starter vs Appwrite Starter 2026

·StarterPick Team
supabasefirebaseappwritebaassaas-boilerplatedatabase2026

TL;DR

Supabase has won the developer mindshare race for SaaS in 2026. PostgreSQL (real SQL, not NoSQL), Row Level Security, built-in auth, storage, edge functions — all in one platform with a generous free tier. Firebase is still dominant in mobile-first and consumer apps (Firebase Cloud Messaging, Crashlytics, Google Analytics integration). Appwrite is the open-source self-hosted alternative for teams with data sovereignty requirements. For most SaaS startups in 2026: Supabase starter is the path of least resistance.

Key Takeaways

  • Supabase: Postgres, RLS, auth, storage, realtime, edge functions — open source, free 500MB DB
  • Firebase: Firestore (NoSQL), Firebase Auth, FCM push, Crashlytics, real-time by default, Google-owned
  • Appwrite: Self-hosted BaaS, Postgres database, auth, storage, messaging — full control
  • SQL vs NoSQL: Supabase = real SQL (relational); Firebase = document store (flexible but costly at scale)
  • Pricing break-even: Supabase free tier lasts longer for most SaaS; Firebase costs grow faster with reads
  • Best for SaaS: Supabase (SQL + RLS = great for multi-tenant)

Supabase Starter

Official Next.js Starter

# Official Supabase Next.js starter:
npx create-next-app -e with-supabase my-app
# Or:
git clone https://github.com/vercel/next.js/tree/canary/examples/with-supabase

Core Patterns

// lib/supabase/server.ts:
import { createServerClient } from '@supabase/ssr';
import { cookies } from 'next/headers';

export async function createClient() {
  const cookieStore = await cookies();
  
  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll: () => cookieStore.getAll(),
        setAll: (cookiesToSet) => {
          try {
            cookiesToSet.forEach(({ name, value, options }) =>
              cookieStore.set(name, value, options)
            );
          } catch {}
        },
      },
    }
  );
}
// Row Level Security — multi-tenant security in SQL:
// SQL migration:
CREATE TABLE projects (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  name TEXT NOT NULL,
  user_id UUID REFERENCES auth.users(id) NOT NULL,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Enable RLS:
ALTER TABLE projects ENABLE ROW LEVEL SECURITY;

-- Users can only see their own projects:
CREATE POLICY "Users see own projects" ON projects
  FOR ALL USING (auth.uid() = user_id);
// Query respects RLS automatically:
const supabase = await createClient();
const { data: projects } = await supabase
  .from('projects')
  .select('*');
// Only returns the current user's projects — RLS enforced by Postgres
// Supabase Auth in Next.js App Router:
import { redirect } from 'next/navigation';
import { createClient } from '@/lib/supabase/server';

export default async function DashboardPage() {
  const supabase = await createClient();
  const { data: { user } } = await supabase.auth.getUser();
  
  if (!user) redirect('/login');
  
  const { data: projects } = await supabase.from('projects').select('*');
  
  return <ProjectList projects={projects ?? []} />;
}

Supabase Pricing

Free tier:
  → 500MB PostgreSQL
  → 1GB storage
  → 2GB bandwidth
  → 50,000 monthly active users
  → Pause after 1 week inactivity

Pro: $25/month
  → 8GB PostgreSQL
  → 100GB storage
  → 250GB bandwidth
  → Unlimited MAU
  → No pause

Firebase Starter

npm install firebase
npx firebase init
// lib/firebase.ts:
import { initializeApp, getApps } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
import { getAuth } from 'firebase/auth';
import { getStorage } from 'firebase/storage';

const firebaseConfig = {
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY!,
  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN!,
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID!,
  storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET!,
};

const app = getApps().length ? getApps()[0]! : initializeApp(firebaseConfig);
export const db = getFirestore(app);
export const auth = getAuth(app);
export const storage = getStorage(app);
// Firestore real-time subscription:
import { collection, onSnapshot, query, where, orderBy } from 'firebase/firestore';
import { db } from '@/lib/firebase';

export function useUserProjects(userId: string) {
  const [projects, setProjects] = useState<Project[]>([]);
  
  useEffect(() => {
    const q = query(
      collection(db, 'projects'),
      where('userId', '==', userId),
      orderBy('createdAt', 'desc')
    );
    
    // Real-time listener (Firebase's superpower):
    const unsubscribe = onSnapshot(q, (snapshot) => {
      const docs = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
      setProjects(docs as Project[]);
    });
    
    return unsubscribe;  // Cleanup
  }, [userId]);
  
  return projects;
}

Firebase Pricing Reality

Spark (free):
  → 1GB Firestore storage
  → 50K reads/day, 20K writes/day, 20K deletes/day
  → 10GB bandwidth
  → CRITICAL: limits reset DAILY — easy to hit in prod

Blaze (pay as you go):
  → Firestore: $0.06/100K reads, $0.18/100K writes
  → A SaaS with 1000 DAU doing 50 reads/session = 1.5M reads/day
  → Cost: 1,500,000 / 100,000 * $0.06 = ~$90/day ← WATCH OUT

Firebase cost optimization requires aggressive Firestore read minimization.


Appwrite Starter

# Self-hosted (Docker):
docker run -it --rm \
  --volume /var/run/docker.sock:/var/run/docker.sock \
  --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
  --entrypoint="install" \
  appwrite/appwrite:1.5.0

# Or use Appwrite Cloud (managed):
npm install appwrite
// lib/appwrite.ts:
import { Client, Account, Databases, Storage } from 'appwrite';

const client = new Client()
  .setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT!)
  .setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID!);

export const account = new Account(client);
export const databases = new Databases(client);
export const storage = new Storage(client);
// Appwrite database query:
import { databases, Query } from '@/lib/appwrite';

const projects = await databases.listDocuments(
  'my-database-id',
  'projects',
  [
    Query.equal('userId', userId),
    Query.orderDesc('$createdAt'),
    Query.limit(10),
  ]
);

Appwrite Pricing

Free (cloud):
  → 75K monthly active users
  → 2GB storage
  → 300GB bandwidth
  → Unlimited databases

Pro: $15/member/month
  → Everything unlimited (within fair use)

Self-hosted: Free forever
  → Your infrastructure costs only
  → Full data control

Comparison Table

SupabaseFirebaseAppwrite
DatabasePostgreSQL (SQL)Firestore (NoSQL)MariaDB (SQL-like)
Auth
Real-time✅ (core feature)
Storage
Edge functions✅ DenoCloud Functions
Self-hosted
SQL queries✅ Full PostgresPartial
Row-level security✅ RLSRules-basedPermissions
Free tier DB500MB1GB2GB
Pricing predictabilityHighLow (reads add up)High

Decision Guide

Choose Supabase if:
  → SaaS with relational data (users, orgs, subscriptions)
  → Need SQL querying power
  → Multi-tenancy via Row Level Security
  → TypeScript + Prisma or Drizzle ecosystem

Choose Firebase if:
  → Mobile-first consumer app (Firebase + Flutter/React Native)
  → Need Firebase Cloud Messaging for push notifications
  → Real-time sync is a core feature (chat, collaborative)
  → Already in Google Cloud ecosystem

Choose Appwrite if:
  → Data sovereignty (self-hosted required)
  → GDPR compliance needs local hosting
  → Open source stack only
  → Developer tools or internal apps with budget constraints

Compare Supabase, Firebase, and Appwrite starters at StarterPick.

Comments