LEARN IT. BUILD WITH IT.

The Supabase Field Manual

Practical Supabase development, from schema and auth to reliable operations

Free to read online
The Supabase Field Manual

About this workbook

A practical guide to building with Supabase and PostgreSQL: schemas, auth and row-level security, client integration, APIs, storage, realtime, functions and operations. Combines introductions, references, guides, patterns and field notes.

THE COMPLETE READING PATH

Explore the chapters.

Read in order or go straight to the problem you are working on. Every chapter is available online.

Part 1: Migration

  1. Verify a self-hosted to hosted Supabase cutover table by table 3 min
  2. Storage buckets and objects don't come with your Postgres dump 2 min

Part 2: RLS & Auth

  1. Hosted Supabase signs user JWTs with ES256, not RS256 or HS256 2 min
  2. Auth hooks are instance config, not rows — bind them per project 3 min
  3. Test RLS with set local role and request.jwt.claims in a transaction 3 min
  4. Magic links: allow-listed redirect, same OTP type on verify, no ghosts 3 min
  5. Custom claims: the access-token hook stamps roles into the JWT 3 min
  6. Disable public signups; mint users server-side with app_metadata 3 min
  7. OAuth callback: exchange the code, check the tenant, set up once 3 min
  8. Anonymous sign-ins mint real authenticated JWTs; gate on is_anonymous 2 min
  9. Verify Supabase user JWTs at the edge with jose and the project JWKS 3 min
  10. Multi-tenancy: tenant id on every row, tenant list in the JWT 3 min
  11. A policy that reads another table runs that table's policies too 3 min
  12. Wrap auth calls in (select …) and index the policy column 3 min
  13. UPDATE policies have two halves; a blocked write succeeds silently 3 min
  14. Resolve the tenant from the host, then rely on the claim, not the URL 3 min

Part 3: Migrations & Pooling

  1. Record each migration's checksum in the same transaction as its DDL 3 min
  2. Use the session pooler on 5432 for DDL; the direct host is IPv6-only 2 min

Part 4: Self-hosting

  1. Self-hosted Supabase: only Kong should face the internet 3 min

Part 5: Backups & Performance

  1. Daily backups roll back a day, PITR a minute; neither restores Storage 3 min
  2. Find slow queries: pg_stat_statements, explain analyze, inspect db 3 min

Part 6: Client & SSR

  1. Publishable and secret keys replace anon and service_role 2 min
  2. SSR: one server client per request, and let it write the cookies 3 min
  3. Server-side: trust getClaims() or getUser(), never getSession() 2 min

Part 7: Data API

  1. PostgREST caps responses at max_rows; page with range() and a count 3 min
  2. Expose only what PostgREST should serve: a narrow schema, no defaults 3 min
  3. RLS hides rows; column privileges hide columns and break select('*') 2 min
  4. A pre-request function is PostgREST middleware: keys, tenants, 403s 3 min

Part 8: Edge Functions & Webhooks

  1. Database Webhooks are pg_net triggers; make every receiver idempotent 3 min
  2. Run an Edge Function per new row: webhook in, secret checked 4 min

Part 9: Extensions & Cron

  1. pg_cron schedules SQL inside Postgres; cross-service jobs stay outside 3 min
  2. pgvector search: a vector column, one model, an RPC with <=>, HNSW 3 min
  3. pgTAP tests schema and policies in SQL, rolled back afterwards 3 min
  4. Wrappers turn Stripe or S3 into foreign tables; keep them private 2 min

Part 10: Getting Started

  1. Supabase is Postgres behind Kong: Auth, PostgREST, Realtime, Storage 3 min
  2. supabase start runs the stack locally; diff, push and gen types there 3 min
  3. Your first table: enable RLS, write one policy, query it 3 min

Part 11: Realtime

  1. Realtime: postgres_changes is easy; Broadcast from triggers scales 3 min

Part 12: Release tooling

  1. Branching gives each PR a database from migrations, without your data 3 min

Part 13: Schema & Postgres

  1. Set created_by in a BEFORE INSERT trigger, never from the client 3 min
  2. A SECURITY DEFINER RPC is a controlled hole in RLS: guard it, pin it 3 min

Part 14: Security

  1. Vault keeps secrets encrypted in Postgres; read them in definer code 2 min
  2. Pin search_path in definer functions; keep extensions out of public 2 min
  3. Security Advisor lints to clear before launch, performance ones after 3 min
  4. Network restrictions and SSL cover Postgres, not the HTTPS APIs 2 min

Part 15: Storage

  1. Storage RLS lives on storage.objects; the folder path is the boundary 3 min
  2. Private files: signed URLs, transform to resize, TUS above 6 MB 3 min

Want help applying the ideas?

Bring the workflow you want to build or improve.