Skip to content
PixelRidge
← All guides

27 September 2026 · Updated 11 October 2026 · 8 min read

Supabase publishable key vs anon key: are they the same, and how to switch (2026)

Supabase is deprecating its legacy anon and service_role keys by the end of 2026. Here's what the new sb_publishable and sb_secret keys are, what breaks in Lovable and Bolt apps, and a safe step-by-step switch.

Short answer: Supabase says it is "deprecating the anon and service_role keys by the end of 2026" (Supabase docs). The replacements are the publishable key (sb_publishable_...), which replaces anon, and the secret key (sb_secret_...), which replaces service_role. Both kinds work side by side, so you can switch one piece at a time, test, and only then turn the old keys off. If your app was built with Lovable, Bolt or another AI tool, check your Edge Functions carefully. That's where most things break.

Is the anon key the same as the publishable key? No. They are different keys that do the same job: Supabase's docs call anon the "legacy version of publishable keys" (Supabase docs). Both are low-privilege and safe in the browser, but the publishable key is a short sb_publishable_... string, not a JWT.

The four keys, in plain words

Key Looks like Safe in the browser? Replaces
Publishable sb_publishable_... (short) Yes anon
Secret sb_secret_... (short) No, server only service_role
anon (legacy) Long string starting with eyJ Yes —
service_role (legacy) Long string starting with eyJ No, server only —

A quick way to tell them apart: the new keys are short strings, while the old ones are long JWTs that start with eyJ. Supabase's docs put it this way: if a tool, tutorial or AI assistant tells you to copy a long key beginning with eyJ, "it was written for the legacy keys" (Supabase docs). Many AI builders and older tutorials still produce the old style, so don't be surprised to find eyJ... keys in a brand-new project.

Why Supabase is changing this

The old keys are long-lived JWTs tied to your project's JWT secret, which made rotating them painful: changing the secret logged everyone out and broke every client at once. The new keys can be created, rotated and deleted one by one. Secret keys also get an extra safety net: if a secret key is used from a browser, Supabase returns HTTP 401 (Supabase migration guide). That doesn't make leaking one harmless, since a script can still use it, but it stops the most common accident: an AI tool pasting the powerful key into frontend code.

What the publishable key does not change

The publishable key has the same low privileges as anon, so "your Row Level Security policies behave the same" (Supabase migration guide). This matters: switching keys does not fix weak database rules. If your tables were readable by anyone with the anon key, they are just as readable with the publishable key. If you haven't checked your RLS policies, do that first. Our guide Is Lovable secure? includes a 20-minute test.

Step-by-step: switching without breaking your app

This follows Supabase's official migration guide, with notes for apps built by AI tools.

1. Find every place the old keys are used

Before you change anything, make a list. Search your code (or your GitHub repo, if your Lovable or Bolt project syncs to one) for eyJ, SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY, anon and service_role. Also check places that aren't in your code:

  • Hosting environment variables (Vercel, Netlify, Lovable, Bolt)
  • Supabase Edge Function secrets
  • Database webhooks and pg_net calls inside Postgres
  • Automations (Zapier, Make, n8n), cron jobs and CI pipelines
  • Mobile apps already installed on users' phones (these can't be updated instantly)

2. Create the new keys

In the Supabase Dashboard go to Settings → API Keys and open the Publishable and secret API keys tab. Supabase creates keys named default next to your existing ones. Nothing stops working at this point.

3. Update the frontend (publishable key)

Replace the anon key with the publishable key wherever your app creates its Supabase client in the browser. With supabase-js it's the same call with a different key:

const supabase = createClient(SUPABASE_URL, 'sb_publishable_...')

Deploy, then log in, sign up and use the main features to confirm everything still loads.

4. Update your server code (secret key)

Replace service_role with a secret key on servers you control: API routes, background jobs, admin scripts. Never put a secret key in a variable that starts with NEXT_PUBLIC_, VITE_ or EXPO_PUBLIC_. Those get bundled into the browser.

For calls from inside Postgres (database webhooks, pg_net), Supabase says to send the key in an apikey header rather than Authorization: Bearer, and to store it in Vault instead of hard-coding it.

5. Update Edge Functions (where AI-built apps usually break)

This is the step that catches people out:

  • The built-in verify_jwt check only understands the legacy JWT keys. Functions that use the new keys need verify_jwt = false in their configuration.
  • Once that's off, your function code must check who is calling it. Otherwise anyone on the internet can call it. Supabase recommends its @supabase/server SDK (with withSupabase) to handle this, or you can verify the user's session yourself.
  • New keys are available to functions as JSON in SUPABASE_PUBLISHABLE_KEYS and SUPABASE_SECRET_KEYS:
const secretKey = JSON.parse(Deno.env.get('SUPABASE_SECRET_KEYS')!)['default']
  • Send new keys in the apikey header. Putting one in Authorization: Bearer causes JWT errors.

If an AI tool wrote your functions, ask it (or a developer) to show you exactly where each function checks the user. "It uses the service role" is not an answer.

6. Check Realtime

If your app uses Supabase Realtime without logged-in users, note that "public Realtime connections are limited to 24 hours unless the connection is upgraded with user-level authentication" (Supabase migration guide). Most apps won't notice. Dashboards left open on a wall screen might.

7. Turn off the legacy keys

When everything runs on the new keys, deactivate anon and service_role in Settings → API Keys. Deactivation is reversible, "so you can re-enable them if you find a client you missed." Watch your logs and error monitoring for a few days afterwards.

In a Lovable or Bolt app: where to look

AI builders put the Supabase keys in slightly different places, so here is where to start:

  • Lovable (connected to your own Supabase project): the Supabase client is usually created in a file such as src/integrations/supabase/client.ts, with the project URL and the public key written into it. Swap in the publishable key there, then check every Edge Function under supabase/functions/ for the service role key.
  • Lovable Cloud: Lovable runs the backend for you, so don't change keys by hand. Check Lovable's own documentation first, and if you plan to move to your own Supabase project, switch to the new keys as part of that move.
  • Bolt: keys usually live in a .env file as VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY. Anything starting with VITE_ ends up in the browser, so only the publishable key may go there. A secret key in a VITE_ variable is a leak, whatever it is called.

In both tools, ask the AI to "replace the Supabase anon key with the publishable key" only after you have read the change yourself. It is easy for a prompt to paste the secret key into the frontend by mistake.

If a secret or service_role key has already leaked

If you've found a secret key in your frontend code, a public GitHub repo or a screenshot, Supabase's advice is: "Don't rush. Fix the root cause of the leak before you rotate anything." Then:

  1. Remove the key from wherever it leaked and make sure the new version of your app no longer includes it.
  2. Create a new secret key.
  3. Replace the old key everywhere it's used and confirm those deployments are live.
  4. Delete the exposed key. This can't be undone, which is why step 3 comes first.
  5. Check your database for signs of misuse: unexpected new users, changed roles, deleted or edited rows.

If the leaked key was a legacy service_role key, this is a good moment to finish the switch to secret keys. Legacy keys can only be rotated by changing the JWT secret, which signs every user out (Supabase troubleshooting guide).

A realistic timeline

For a typical small app (one frontend, a few Edge Functions, no mobile app), the switch takes an afternoon for a developer, plus a few days of watching logs before you turn the old keys off. Leave more time if you have a mobile app in the stores, since older versions on users' phones will keep using the old key until they update. Don't leave it until December.

FAQ

Is the anon key the same as the publishable key? No. They are different keys with the same job. The publishable key (sb_publishable_...) is the newer replacement for the legacy anon key, which is a long JWT starting with eyJ. Both are low-privilege keys that are safe in the browser when your row level security is right.

Where do I find the service_role or secret key in Supabase? In the Supabase dashboard under Settings > API Keys. Supabase says every key lives there, legacy or not. The secret key (sb_secret_...) and the legacy service_role key bypass row level security, so keep them on the server only: never in browser code, a public repo or a front-end .env file.

Is the Supabase publishable key safe to put in the browser? Yes. It is designed to be public, like the old anon key, but only if Row Level Security protects every table. Without RLS, anyone with the key can read your data.

When will the anon and service_role keys stop working? Supabase says it is deprecating them by the end of 2026. Check the official API keys page for the exact date, and don't wait until the last month.

What is the difference between sb_publishable and sb_secret keys? The publishable key (sb_publishable_...) is for the browser and respects RLS. The secret key (sb_secret_...) bypasses RLS and belongs only on a server or in an Edge Function.

Do I need to change anything in a Lovable or Bolt app? Yes, if it uses your own Supabase project. Update the client file or .env with the publishable key, update Edge Function secrets with the secret key, test, then turn off the legacy keys.

Does this affect apps built with Lovable or Bolt? Yes, if the app uses your own Supabase project. See Lovable app fixes and our Supabase RLS audit, and if you're building for users in India, how we work in India and what happened when Supabase was blocked there.


Rather not do it yourself? Switching keys is included in our Launch Care plans, and it's a fixed-price item in our Launch Readiness Audit. We'll also check your RLS policies and Edge Functions while we're in there, since that's where the real risk usually is. See our Supabase RLS audit, get a free Launch Check, or try our pricing calculator for an estimate.

Based on Supabase's documentation as of September 2026. Supabase may change the timeline; check the official API keys page for the latest.

Rather get it by email?

Leave your name and email, plus your app link if you like. We reply with a free Launch Check, no obligation.

We email you about this request only, and you can reply “unsubscribe” at any time. Prefer email? Write to info@pixelridgeweb.com. See our privacy notice.

Need it fixed for you? Lovable app fix and security audit, Fix and launch your Bolt.new app, Review and secure an app built with Cursor or Supabase RLS audit: row level security and key review.

Want a second pair of eyes on your app?

Send us your live link. We record a short video showing the top risks we can see, free and with no obligation.

Terms and conditions apply. Read the terms.