Supabase is retiring anon and service_role keys by the end of 2026: how to migrate to publishable and secret keys safely
Short answer
Supabase is deprecating the legacy JWT-based anon and service_role keys by the end of 2026. Their replacements are publishable keys (sb_publishable_…), which are safe in browsers and map to the anon or authenticated role under Row Level Security, and secret keys (sb_secret_…), which map to service_role, bypass every RLS policy and must never appear in a web page, mobile bundle, source code, URL or log. Migrate by creating the new keys, replacing the publishable key in clients and the secret key only in servers and Edge Functions, verifying, and then deactivating the old keys.
Last updated · Sekrd Research
- Legacy
anonandservice_roleJWT keys are being deprecated by the end of 2026 (Supabase docs). - Publishable key
sb_publishable_…: low privilege, safe in clients, governed by RLS. - Secret key
sb_secret_…: maps toservice_role, which hasBYPASSRLS— it skips every policy. - Secret keys must never be in a web page, public document, source code, bundled app, URL, query parameter or unsanitized log.
Which key goes where
| Key | Role | Allowed in |
|---|---|---|
sb_publishable_ (replaces anon) | anon / authenticated, RLS applies | Browsers, mobile apps, CLIs |
sb_secret_ (replaces service_role) | service_role, bypasses RLS | Servers, Edge Functions, admin tools only |
The mistake to avoid during migration
Migrations are when secret keys leak. An AI assistant asked to “replace the Supabase keys” will often update every environment variable it can find, including ones prefixed for the client build (VITE_, NEXT_PUBLIC_, EXPO_PUBLIC_). Anything with those prefixes is inlined into JavaScript that every visitor downloads. A secret key there gives anyone full read and write access to your database, regardless of RLS.
In Sekrd’s dataset of 799 publicly reachable hosts scanned between March and September 2026, two hosts shipped what looked like a Supabase service_role key in client code, and high-severity secret leaks of any kind appeared on 2.1% of hosts.
Safe migration steps
- Create a publishable key and a secret key in the dashboard (Project Settings → API Keys).
- Replace the anon key in client code with the publishable key. Nothing else changes for the client: RLS still decides access.
- Replace the service_role key with the secret key only in server-side environments and Edge Function secrets.
- Search the built frontend for the old and new secret values before deploying:
grep -rE "sb_secret_|service_role" dist/ .next/static/ build/ 2>/dev/null - Deploy, confirm every component uses the new keys, then deactivate the legacy keys.
If a secret key has already leaked
Treat it as a full database compromise: create a new secret key, replace it everywhere server-side, delete the leaked key, then review recent data changes. Removing the key from your repository is not enough — it has already been served to browsers and may be cached or archived.
Frequently asked questions
When are Supabase anon and service_role keys deprecated?
Supabase’s documentation states it is deprecating the legacy anon and service_role JWT keys by the end of 2026, replaced by publishable (sb_publishable_) and secret (sb_secret_) keys.
Can I put the Supabase publishable key in my frontend?
Yes. The publishable key is designed for clients. Access is controlled by Row Level Security policies, so every table it can reach must have RLS enabled with correct policies.
What happens if my Supabase secret key is exposed?
The secret key maps to the service_role role, which bypasses all Row Level Security. Anyone holding it can read and modify every table. Rotate it immediately by creating a new secret key, replacing it server-side and deleting the leaked one.
Sources
Don't ship until you're sekrd
Run a free scan to find the vulnerabilities your AI missed.
Scan Your App Free