Supabase Full-Stack Backend
Build backends with Supabase: PostgreSQL with RLS, auth (magic links, OAuth), real-time subscriptions, storage, and Edge Functions.
Supabase is an open-source Firebase alternative providing PostgreSQL with Row Level Security, authentication, real-time subscriptions, object storage, and Edge Functions. It eliminates backend boilerplate for most web applications.
Use RLS for all user-facing tables - it's the security layer between your data and the internet. Start with Supabase Auth rather than rolling your own. Edge Functions for server-side logic that shouldn't run client-side. Self-host or use managed for production.
Workflow
- Set up the Supabase clientThe Supabase JS client handles auth tokens, RLS, and real-time subscriptions automatically.
- Implement Row Level SecurityWithout RLS, any authenticated user can read/write all rows - a critical security hole.
- Add authenticationSupabase Auth handles JWT sessions, OAuth providers, and magic links out of the box.
- Use real-time subscriptionsReal-time lets you push database changes to clients without polling.
- Deploy Edge Functions for server logicEdge Functions run server-side Deno code at the edge - for webhooks, Stripe handling, and secrets you can't expose client-side.
Output Format
RLS policies for all tables, Supabase Auth with chosen providers, real-time subscription for live features, Edge Functions for server-side logic, service role key never exposed to client.
Examples
RLS policy: `CREATE POLICY "team members can view org data" ON tasks FOR ALL USING (EXISTS (SELECT 1 FROM org_members WHERE org_id = tasks.org_id AND user_id = auth.uid()))`Real-time: `const channel = supabase.channel("messages").on("postgres_changes", { event: "INSERT", schema: "public", table: "messages", filter: `channel_id=eq.${id}` }, (payload) => setMessages(m => [...m, payload.new])).subscribe()`Edge Function: `import Stripe from "https://esm.sh/stripe@13"; const stripe = new Stripe(Deno.env.get("STRIPE_KEY")!); Deno.serve(async req => { const sig = req.headers.get("stripe-signature")!; const event = stripe.webhooks.constructEvent(await req.text(), sig, WEBHOOK_SECRET); ... })`Edge Cases & Gotchas
- Service role key: never use in client-side code - it bypasses all RLS. Store only in Edge Functions and server environments
- RLS performance: complex policies with JOINs can slow down queries; add appropriate indexes on the columns used in USING clauses
- Auth session refresh: Supabase auto-refreshes tokens; on server components (Next.js), use `@supabase/ssr` middleware to refresh cookies on each request
When to Break These Rules
- For complex multi-tenant applications with sophisticated access control, custom PostgreSQL row-level security policies may become too complex - consider an explicit authorization layer (like Permit.io or Ory Keto).
Reference Files
Supabase docs: https://supabase.com/docsSupabase Auth: https://supabase.com/docs/guides/authRow Level Security: https://supabase.com/docs/guides/database/postgres/row-level-securityEdge Functions: https://supabase.com/docs/guides/functions