Quick Guide Updated January 2026

Supabase Anon Key vs Service Key

Understanding the difference between these two keys is crucial for Supabase security. This guide explains when to use each and what happens if they're exposed.

The Two Keys at a Glance

Anon Key

Public / Client-safe

  • Safe to use in browsers
  • Safe to commit to public repos
  • Subject to RLS policies
  • Limited to anon role permissions

Service Role Key

Secret / Server-only

  • Never use in browsers
  • Never commit to repos
  • Bypasses ALL RLS policies
  • Full database access

How They Work

When you create a Supabase project, you get two API keys. They look similar (both are JWTs), but they grant completely different levels of access.

Request Flow with Anon Key
Client App
Request with anon key
Supabase API
Supabase API
Query as 'anon' role
PostgreSQL
PostgreSQL
RLS Policies Applied
Filtered results

Anon Key: Designed to be Public

The anon key is intentionally designed to be exposed in your frontend code. It's not a secret - your security doesn't depend on hiding it.

// This is SAFE in client-side code
const supabase = createClient(
  'https://xxx.supabase.co',
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' // anon key
)

When a request uses the anon key:

Service Role Key: Full Access

The service role key bypasses Row Level Security entirely. It's the "admin" key that can do anything.

// This should ONLY be in server-side code
const supabaseAdmin = createClient(
  process.env.SUPABASE_URL,
  process.env.SUPABASE_SERVICE_ROLE_KEY // NEVER expose this
)
If service_role key is exposed...

An attacker can read ALL data in your database, modify ANY row, delete entire tables, and create admin accounts. There is no RLS protection.

Comparison Table

Feature Anon Key Service Role Key
Safe in browser? Yes Never
RLS applies? Yes Bypassed
PostgreSQL role anon service_role
Use case Client apps, public APIs Server functions, admin tasks
If exposed Limited by RLS Full database access

When to Use Each Key

Use Anon Key For:

Use Service Role Key For:

Common Mistakes

Mistake 1: Using NEXT_PUBLIC_ for Service Key

# WRONG - This exposes the key in your bundle!
NEXT_PUBLIC_SUPABASE_SERVICE_KEY=eyJ...

# CORRECT - No NEXT_PUBLIC_ prefix
SUPABASE_SERVICE_ROLE_KEY=eyJ...

Mistake 2: Using Service Key "Just to Be Safe"

Some developers think using the service key is "more secure." It's the opposite - you're bypassing all your security policies!

Mistake 3: Committing Keys to Git

Even if your repo is private, never commit the service role key. Use environment variables and .env.local files that are gitignored.

How to Check Which Key You're Using

Use our JWT Decoder to inspect any Supabase key:

// Decode the JWT payload
// Anon key will have: { "role": "anon" }
// Service key will have: { "role": "service_role" }
Pro Tip

If you're not sure which key is in your code, paste it into our API Key Identifier to instantly find out.

What If My Service Key Is Exposed?

If you've accidentally exposed your service role key:

  1. Rotate immediately - Go to Project Settings → API and regenerate the key
  2. Audit your database - Check for unauthorized changes or data access
  3. Review logs - Look for suspicious queries in Supabase logs
  4. Update your code - Replace the old key with the new one in all environments

Check if your keys are exposed

Scan your website to find any leaked API keys in your client-side code.

Scan Your Site