Supabase foundations

Separate public and secret keys

Understand publishable or anonymous client keys, server-only secret keys, JWT context, and why RLS remains mandatory.

9 minute lesson

~~~

Every Supabase project ships with two kinds of API credentials, and mixing them up is the fastest way to turn a small bug into a data breach.

The publishable key (named sb_publishable_...; older projects call it the anon key) is safe to ship in a browser or mobile app. It identifies your Supabase project; it does not grant unrestricted database authority by itself. Requests made with it run through Row Level Security, and the user session adds identity claims on top.

The secret key (sb_secret_..., or the legacy service_role JWT) is a different animal. Clients created with it bypass Row Level Security entirely:

import { createClient } from '@supabase/supabase-js'

// server-side code only
const admin = createClient(
  process.env.SUPABASE_URL,
  process.env.SUPABASE_SECRET_KEY
)

const { data } = await admin.from('notes').select()
console.log(data.length)
// every note from every user — no policy applied

That power is why secret keys must never reach a browser, mobile bundle, log line, or public repository. A leaked privileged key is an authorization incident: every RLS policy you wrote stops protecting anything until you rotate the key.

Verify what your build ships

Do not trust the mental model — check the artifact. After building your frontend:

grep -R "sb_secret" dist/
# (no output — this must find nothing)

grep -R "service_role" dist/
# (no output)

If either command prints a match, a privileged key made it into client code. Rotate it in the dashboard under Settings → API Keys immediately, then fix the import that leaked it. Rotation is not optional after exposure; the key does not expire on its own.

The inventory habit

Take a small app and inventory every environment variable it uses. For each one, write three facts: can it enter client code, where does the server-only copy live, and how do you rotate it. The project URL and the publishable key can be public. The database password, the secret key, and SMTP credentials stay server-side, in your deployment platform’s secret store.

One warning to keep intact: the publishable key is only safe to expose while RLS is enabled and correct on every exposed table. A public key plus an unprotected table is a public table.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →