Skip to content

ADR-001: Use Clerk for Authentication

Status

Accepted (2026-03-06)

Context

Reggie originally used Supabase Auth for authentication. This created several problems:

  1. Dev/prod mismatch: Local dev required 10 Supabase Docker containers (3GB+ images) just for auth + Postgres. Production used RDS with no Supabase, causing migration failures.
  2. Heavy local setup: supabase start took minutes and only Postgres and Auth were actually used.
  3. Auth coupling blocked cleanup: Alembic migrations referenced auth.users (Supabase-specific schema), forcing SKIP_MIGRATIONS=true on RDS.
  4. No pre-existing customers: Zero users existed, making this a clean swap with no data migration.

The project needed an auth provider that: - Works with both Next.js frontends and FastAPI backend - Supports networkless JWT verification (no round-trip to auth provider on every request) - Has built-in UI components to reduce frontend auth code - Simplifies local development

Decision

Replace Supabase Auth with Clerk across the entire stack.

Architecture after migration: - Frontend: @clerk/nextjs with ClerkProvider and built-in components (UserButton, Show) - Backend: RS256 JWT verification using Clerk's PEM public key (networkless -- no API calls to Clerk) - User linking: profiles.clerk_id column maps Clerk users to Reggie profiles - Local dev: Clerk keyless mode -- no Clerk account needed, auto-generates temporary keys

What changed: | Component | From | To | |-----------|------|----| | Frontend auth | @supabase/ssr + custom middleware | @clerk/nextjs + clerkMiddleware() | | Backend JWT | Supabase JWKS/HS256 | Clerk RS256 with PEM key | | Local database | supabase start (10 containers) | Docker Postgres (1 container) | | User management | Supabase Dashboard | Clerk Dashboard |

Consequences

Easier: - Local dev starts in seconds (1 Docker container vs 10) - No Supabase dependency in production -- clean RDS + ECS architecture - Built-in UI components reduce frontend auth code significantly - Networkless JWT verification means no auth latency on API calls

Harder: - Clerk is a paid service (free tier covers current scale) - Clerk keyless mode is dev-only -- production requires a Clerk account - All existing documentation referencing Supabase Auth needed updating

Related: plans/clerk-auth-migration.md (full implementation plan)