Supabase for AI SaaS: Auth, Storage, and Signed URLs in Practice
How we use Supabase in a production AI product: magic link auth, JWT verification in Express, private storage with signed URLs, and pgvector on the side.
Ostap Kovalisko
Founder & AI Systems Architect
Supabase gets pitched as "Firebase but Postgres." For AI SaaS it's something more specific: auth, file storage, and a real Postgres you can attach pgvector to — three problems solved with one bill. We run it under a production AI platform with a Next.js frontend and an Express backend on Railway. Here's how the pieces actually fit, including the parts the docs gloss over.
Magic Links: Right Default for B2B AI Tools
We ship passwordless magic link auth for internal-facing AI products. Business users live in their inbox, there's no password reset flow to support, and no credentials to leak. Three lessons from production:
- Send through your own SMTP provider. Supabase's built-in sender is rate-limited (a handful of emails per hour) and lands in spam. Wire SendGrid or similar with your domain and DKIM — this is the #1 "auth is broken" report you'll avoid.
- Handle the corporate link-scanner problem. Email security tools pre-click links, which can consume one-time tokens. A confirmation page with a button ("Continue to sign in") instead of auto-consuming on GET fixes it.
- Set session lifetimes for daily-use tools. Nobody should re-authenticate every morning. Long refresh-token life plus an allowlist check at login works for closed B2B products.
The JWT Is the Contract Between Frontend and Backend
Our AI logic lives in Express, not in Supabase edge functions. The integration is simple: the Next.js client attaches the Supabase JWT as a Bearer token; Express verifies it (JWKS or shared secret) and derives the user server-side. Two rules we treat as non-negotiable:
- Never accept a user ID from the request body — always derive it from the verified token
- Apply the derived permission scope inside retrieval queries, so the agent can't summarize a document its user couldn't open
The service-role key lives only in the backend and the sync workers. It bypasses RLS entirely — treat it like a database password, because it is one.
Storage and Signed URLs: The Pattern That Matters
AI products are file-heavy: users upload contracts and spreadsheets, agents generate reports and charts. All our buckets are private; nothing is ever publicly readable. Access flows through short-lived signed URLs minted by the backend after a permission check:
| Flow | Pattern | URL expiry |
|---|---|---|
| User upload | Backend mints signed upload URL → client PUTs directly | ~10 min |
| Viewing a document | Signed URL per request, after auth check | 1 hour |
| Agent-generated artifacts | Worker writes with service role, stores path in Postgres | Signed on read |
| LLM vision input | Short-lived signed URL passed to the model API | ~5 min |
Two gotchas: store the storage path in your database, never a signed URL (they expire and end up cached broken in the UI); and route uploads directly to storage via signed upload URLs instead of through your API — proxying multi-megabyte PDFs through Express is a self-imposed bottleneck.
Postgres Is the Quiet Win
The most valuable Supabase feature for AI SaaS is the least flashy one: it's real Postgres. Your app data, your synced records, and your pgvector embeddings live in one database with real joins.
Our sync workers upsert nine sources into Postgres, and pgvector holds 38,000+ embeddings alongside. Retrieval queries can filter by permission, company, and recency in the same statement that ranks by similarity — no cross-store consistency dance with a separate vector DB.
Where We Deviate from the Defaults
- RLS as backstop, not primary authorization — with all access flowing through the backend, complex policy logic lives in code where it can be tested; RLS guards against mistakes
- No heavy logic in edge functions — agent runs are long-lived; they belong on Railway
- Nightly dumps to separate storage — backups you haven't restored are hypotheses, and synced-in data makes restores messy; practice one
Net: Supabase removes roughly a month of undifferentiated auth and storage work from an AI SaaS build. Spend that month on retrieval quality instead — that's where your product is actually decided.
Let's Talk About Your Project
Have questions about nearshoring or AI development? Our team is here to help you make the right decision.
- ✓Free consultation on your AI project
- ✓Custom cost estimates and timeline
- ✓Access to nearshore talent pools