If your Supabase project still uses the familiar anon and service_role API keys, this is now a migration task rather than a future cleanup idea.
Supabase’s current documentation says the legacy keys are being deprecated by the end of 2026. The replacement model uses publishable keys for public clients and secret keys for trusted backend components.
The migration itself is not difficult. The dangerous part is assuming it is only a string replacement.
A production app may use Supabase credentials in the browser, server routes, Edge Functions, Cloudflare Workers, scheduled jobs, webhooks, CI/CD, local environment files and third-party integrations. Change the wrong credential in the wrong trust boundary and you can either break production or accidentally give a public client privileged access.
The replacement map is simple
Supabase’s official migration guide maps the old keys like this:
| Legacy key | Replacement | Typical location |
|---|---|---|
anon |
Publishable key | Browser, mobile, desktop, public clients |
service_role |
Secret key | Servers, Edge Functions, Workers, trusted backend code |
See the current Supabase API key documentation and migration guide.
The important word is location. Before replacing anything, identify where each credential is actually running.
First, inventory every place your app uses Supabase
Do not start by searching only the frontend repository.
Check:
- browser environment variables;
- SSR/server environment variables;
- Supabase Edge Functions;
- Cloudflare Workers or other API layers;
- background jobs and scheduled tasks;
- webhook handlers;
- CI/CD secrets;
- deployment-platform environment variables;
- local
.envfiles used by developers; - scripts and admin utilities;
- third-party services that call Supabase directly.
AI-built applications make this especially important because the first working version may have accumulated configuration across several tools before anyone documented the architecture.
Create a small table with credential → runtime → purpose → owner → migration status. That turns an invisible security dependency into something you can verify.
Publishable does not mean unrestricted
Supabase explicitly says its publishable key is safe to expose in a public client when Row Level Security and least-privilege access are configured correctly.
That distinction matters.
The key identifies the application component. It does not replace your authorization model.
If a browser can access a table through the Data API, your RLS policies and database grants still decide what the current user is allowed to read or change. A public key cannot rescue an unsafe policy, and hiding a public key cannot substitute for one.
If this boundary is unclear in your project, read my guide on whether the Supabase anon key is safe to expose.
Secret keys belong only on trusted backend infrastructure
Supabase’s current security guidance is unambiguous: secret and legacy service-role keys must never be exposed on the frontend because they can bypass RLS.
That means they do not belong in:
- browser bundles;
- public JavaScript;
- mobile code that users can inspect;
- public GitHub files;
- screenshots or documentation pasted into public tickets.
Keep privileged credentials in the secret/environment-variable system of the server, Worker, Edge Function or deployment platform that needs them.
Supabase also says its newer secret-key formats can be revoked and that secret keys detected in public GitHub repositories can be automatically revoked through GitHub secret scanning. That is useful protection, but it is not a reason to become casual about credential handling.
Do not reuse one Supabase client for user and admin work
A common production mistake is creating one client and allowing its authorization context to change during a request.
Supabase’s current troubleshooting documentation notes that an SSR client initialized for privileged access can still end up using a user’s session token in its Authorization header. In that situation, requests can unexpectedly be evaluated as the user instead of bypassing RLS.
For privileged server operations, keep the admin/secret client separate from user-session clients.
That separation also makes the migration easier to reason about: one client represents the user; another represents trusted backend authority.
Migrate in parallel instead of flipping everything at once
Supabase says legacy and new key types can work simultaneously during migration.
Use that overlap.
A safer sequence is:
- inventory every current credential use;
- create or retrieve the appropriate publishable and secret keys;
- migrate one runtime at a time;
- deploy;
- test the real production path;
- inspect logs and failed requests;
- continue until every known dependency uses the new model;
- deactivate legacy keys only after verification.
Do not rotate the old keys first and then discover which forgotten webhook, Worker or admin script depended on them.
Verify business flows, not just API connectivity
A health check that can SELECT 1 does not prove your application survived the migration.
Test the flows that matter to the business:
- sign-up and sign-in;
- authenticated reads;
- user-owned writes;
- admin operations;
- file uploads;
- payments and payment callbacks;
- webhooks;
- emails triggered by backend functions;
- scheduled jobs;
- account deletion or other privileged operations.
For each flow, verify both the user-facing result and the resulting backend state.
A successful button click is not enough if the database write failed. A successful database write is not enough if the downstream webhook never ran.
Watch for a second Supabase change: table exposure
There is another 2026 platform change worth separating from API-key migration.
Supabase announced that new tables are no longer automatically exposed to its Data and GraphQL APIs under the newer default behaviour, with enforcement for existing projects scheduled for October 30, 2026. Projects that rely on the Data API may need explicit grants for tables created by migrations or tooling.
See the official Supabase changelog on Data API table exposure.
Do not misdiagnose a missing grant as an API-key migration failure. They affect the same access path, but they are different controls.
Treat the migration as an architecture check
The best outcome is not merely that your app uses newer strings.
You should finish knowing:
- which components are public;
- which components hold privileged authority;
- where secrets are stored;
- which tables public clients can reach;
- what RLS protects;
- which background integrations depend on Supabase;
- how you can rotate credentials again without guessing.
That is a much stronger production position than “the app works.”
If an AI-built product has reached the point where credentials, RLS, deployment environments and backend authority are becoming difficult to reason about, use my AI-built app production checklist. If you need help getting the architecture production-ready, see my MVP development service or contact me.



