← Learn

Definition

Supabase anon key vs service_role key: what's the difference?

We scanned nearly 2,000 AI-built apps and 1 in 8 shipped a high-severity flaw. Want to check yours?Scan free β†’

The Supabase anon key is a public key meant to ship to the browser; it respects Row Level Security, so it can only do what your policies allow. The service_role key bypasses RLS entirely and has full admin access, so it must only ever be used server-side and must never appear in client code or a public repo.

The anon (publishable) key

Safe to expose, by design. It identifies your project and carries the authenticated user's permissions. Its safety depends entirely on RLS being configured, because without policies it can read and write everything. This is the key you put in the browser.

The service_role (secret) key

Never safe to expose. It skips all RLS and can do anything in your database. It belongs only in server code, edge functions, or route handlers, read from an environment variable, never in a client component or prefixed for the browser.

Which key goes where

The anon key is the only one that belongs in client code. In Next.js it carries the NEXT_PUBLIC_ prefix precisely because it is meant to be public. The service_role key must be read from a server-only environment variable (no public prefix) and used only in code that never reaches the browser.

// Browser / client component: anon (publishable) key is fine here
const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, // public, respects RLS
);

// Server route / edge function only: service_role bypasses RLS
const admin = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_ROLE_KEY!, // NO NEXT_PUBLIC_ prefix, never in the browser
);

Is the anon key safe to expose?

Yes, but only if Row Level Security is turned on for every table it can reach. The anon key is public on purpose, so its safety is not about hiding it, it is about your RLS policies. With RLS off, that public key can read and write your whole database, which is how most exposed-Supabase incidents actually happen.

Anon key vs publishable key: same key, new name

Supabase renamed its API keys: the anon key is now also called the publishable key, and the service_role key is now the secret key. They behave the same, and everything here applies to both names. If a newer project shows a publishable key, that is your anon key, safe in the browser as long as Row Level Security is on. The secret key is the service_role key and must stay server-side.

What happens if the service_role key leaks

Full database takeover. Because it bypasses RLS, anyone holding it can read every row, edit or delete records, and drain or wipe your data, no login required. If it has ever appeared in a browser bundle, a public repo, a client-side environment variable, or a screenshot, treat it as compromised: rotate it in the Supabase dashboard immediately, then move it to a server-only variable.

Anon key vs service_role key at a glance

anon / publishable keyservice_role / secret key
Respects RLSYesNo, bypasses it entirely
Safe in the browserYes, if RLS is onNever
Where it belongsClient and server codeServer code only
Next.js prefixNEXT_PUBLIC_No public prefix
If exposedFine when RLS is configuredFull database takeover, rotate now

What this means for AI-generated code

AI tools sometimes reach for the service_role key to make an operation work without configuring RLS, and then place it in client-reachable code. If that key ends up in a browser bundle or a public repo, anyone can take full control of your database. Rotate it immediately if it was ever exposed.

Common questions

Is the Supabase anon key safe to expose?

Yes, the anon (publishable) key is designed to be public and ship to the browser. It is only safe if Row Level Security is enabled on every table it can reach, because without policies it can read and write everything.

Where do I use the service_role key?

Only on the server: route handlers, server actions, edge functions, or a backend. Read it from a server-only environment variable with no public prefix, and never reference it in a client component or commit it to a public repo.

What is the difference between the anon key and the publishable key?

They are the same key. Supabase renamed the anon key to the publishable key and the service_role key to the secret key. The behavior is identical, so anything written about the anon or service_role key applies to the new names too.

My service_role key was exposed, what do I do?

Rotate it right away in the Supabase dashboard under Project Settings, API. Then move the new key into a server-only environment variable, and check your database logs for any unexpected reads or writes while the old key was live.

Can I use the anon key on the server?

Yes. The anon key works on both client and server. Use the service_role key on the server only when you deliberately need to bypass RLS, for example an admin task or a trusted background job.

Want to know if your app has this issue? Scan your live app or a public repo free, no account needed.

Scan my app β†’

Related: fix an exposed Supabase key

Supabase Anon Key vs Service Role Key: What's the Difference?: Prbl