Providers / Supabase
Databases
Supabase API keys and credentials
What every Supabase credential a founder holds does, whether it expires, and what tends to break. Each fact links to Supabase's own docs.
At a glance
| Credential | Expiry | Permissions |
|---|---|---|
| Management API personal access token (sbp_) | You choose | Can be scoped |
| Legacy anon key (JWT) | Doesn't expire | Not documented |
| Legacy service_role key (JWT) | Doesn't expire | Not documented |
| Publishable key | Not documented | Not documented |
| Secret key (server-side, non-JWT) | Not documented | Not documented |
| JWT signing key (asymmetric) | Not documented | Full access only |
| Postgres database password | Not documented | Full access only |
How to rotate the Legacy service_role key (JWT)
- In Settings > API Keys, open the "Publishable and secret API keys" tab and create the new keys. Creating them is safe: your legacy keys keep working. Supabase docs
- Swap the secret key into every backend you control. Secret keys bypass row-level security, so keep them out of client code and source control. Supabase docs
- Update Database Webhooks and pg_net calls to send the secret key in the apikey header instead of Authorization: Bearer, and store it in Vault. Supabase docs
- Update Edge Functions to read the SUPABASE_PUBLISHABLE_KEYS and SUPABASE_SECRET_KEYS environment variables, and authorize requests in your own code (verify_jwt = false) or with the @supabase/server SDK. Supabase docs
- Replace the legacy anon key with a publishable key in browser and mobile clients. Supabase docs
- Check that nothing still uses the legacy keys (mobile app versions in users' hands, CI/CD, third-party integrations, cron jobs, workers). Supabase says there is no usage indicator, so this is a manual check. Supabase docs
- Deactivate the legacy keys in Settings > API Keys. This is reversible. Supabase docs
- If the service_role key leaked, also revoke the legacy JWT secret, because the legacy keys are JWTs signed by that secret. Follow "Getting started" in the JWT signing keys guide, and deactivate the legacy keys first. Supabase docs
Can the old and new key work at the same time? Yes. Supabase says "Both key systems work at the same time" and creating publishable and secret keys does not revoke the legacy keys, so you can move clients one at a time.
Revoking the old one: Deactivate the legacy keys in Settings > API Keys (or through the Management API, where the rotate-leaked guide says to confirm the response shows "enabled": false). If one was leaked, also revoke the legacy JWT secret. If you find a missed client afterwards, move it to a new key rather than re-enabling the legacy keys, because re-enabling restores the compromised key. Unless the key is being actively abused, wait until every component uses the new key before you start.
Source: supabase.com/docs/guides/security/rotate-leaked-api-keys, checked
Does the Legacy service_role key (JWT) expire?
No. The Legacy service_role key (JWT) doesn't expire on its own: it works until you revoke it.
What breaks when the Legacy service_role key (JWT) expires
The legacy key has no expiry date; it stays valid until you disable it, and Supabase says it is deprecating the anon and service_role keys by the end of 2026. Once deactivated, any client still sending it loses access. The docs give no error text for that case, so look for failed requests from backends, webhooks, cron jobs and old app versions. Separately, the migrating-to-new-api-keys guide says a Database Webhook that sends a new secret key as an Authorization: Bearer token is rejected, because the new keys are not JWTs (it lists no error text for that case).
Other things that often go wrong with Supabase:
- Legacy anon or service_role key is deactivated during a migration and clients that still use it start failing
- Legacy JWT secret is revoked before its tokens expire, which breaks sessions that still rely on it
- Management API personal access token expires and CI migrations or key provisioning stop working
- Database password reset does not take effect, causing failed connections
How to rotate the Legacy anon key (JWT)
- In Settings > API Keys, open the "Publishable and secret API keys" tab and create a publishable key. Your legacy keys keep working. Supabase docs
- Swap the publishable key into public code (browsers, mobile and desktop apps, distributed CLIs). It has the same low privileges as anon, so row-level security policies behave the same. Supabase docs
- Check that nothing still uses the legacy anon key, including app versions already in users' hands. There is no usage indicator, so this is a manual check. Supabase docs
- Deactivate the legacy keys in Settings > API Keys. This is reversible. Supabase docs
Can the old and new key work at the same time? Yes. Both key types work simultaneously, so you can swap clients one at a time.
Revoking the old one: Deactivate the legacy keys in Settings > API Keys. Supabase says this is reversible, but advises moving a missed client to a new key rather than re-enabling a compromised legacy key.
Source: supabase.com/docs/guides/getting-started/migrating-to-new-api-keys, checked
Does the Legacy anon key (JWT) expire?
No. The Legacy anon key (JWT) doesn't expire on its own: it works until you revoke it.
What breaks when the Legacy anon key (JWT) expires
The legacy anon key has no expiry date and stays valid until you disable it; Supabase says it is deprecating it by the end of 2026. Once deactivated, clients still using it (older mobile app versions especially) lose access. The docs give no error text for this.
How to rotate the Secret key (server-side, non-JWT)
- Create a new secret key in Settings > API Keys (or with the Management API, from a local terminal rather than CI, because the command prints the key value). Supabase docs
- Replace the old key with the new one everywhere your application uses it. Edge Functions that use auth: 'secret' accept only the key named default, so use the new key's name there. Supabase docs
- Delete the old key in Settings > API Keys (or list keys with the Management API, delete the old one by id, and list again to confirm). Supabase docs
Can the old and new key work at the same time? Yes. The rotate-leaked guide has you replace the key everywhere before deleting the old one. The api-keys page advises one secret key per backend component, so more than one secret key can exist at once.
Revoking the old one: Delete the old key in Settings > API Keys. Deleting a secret key can't be undone, so replace it everywhere first. If someone is actively using a leaked key, delete it immediately, accepting that components using it break until replaced.
Source: supabase.com/docs/guides/security/rotate-leaked-api-keys, checked
Does the Secret key (server-side, non-JWT) expire?
Supabase's docs don't say whether the Secret key (server-side, non-JWT) expires.
What breaks when the Secret key (server-side, non-JWT) expires
Supabase documents no expiry for secret keys. If one is deleted, components still using it lose access; the rotate-leaked guide gives no error text. Per the api-keys page, a secret key used in a browser returns HTTP 401 Unauthorized. Per the migrating-to-new-api-keys guide, a secret key sent as Authorization: Bearer to Edge Functions is rejected with Invalid JWT.
How to rotate the JWT signing key (asymmetric)
- On the JWT signing keys page, click "Migrate JWT secret". This imports the legacy secret and creates a new asymmetric standby key. (For a later rotation, create a new standby key instead.) Supabase docs
- Before rotating, confirm your app does not verify JWTs directly against the legacy secret, turn off "Verify JWT" on Edge Functions that use it, and verify tokens with supabase.auth.getClaims(). Supabase docs
- Click the rotate button. Auth starts signing new tokens with the new key, and the old key becomes "Previously used" but is still trusted. Supabase docs
- Wait before revoking the previous key. With a 1-hour access token expiry, wait at least 1 hour 15 minutes after it moves to "Previously used". Supabase docs
- Revoke the previous key (or the legacy JWT secret). If you use the legacy keys, disable them before revoking the legacy secret. Supabase docs
Can the old and new key work at the same time? Yes. After rotation both keys are accepted: rotation only changes the key Auth uses to create new JWTs. The previously used key stays trusted until you revoke it.
Revoking the old one: Revoke the previous key once all regularly valid JWTs signed with it have expired, or sooner in an emergency. A revoked key can be moved back to standby; only permanent deletion is irreversible. Most state changes are throttled for about 5 minutes.
Source: supabase.com/docs/guides/auth/signing-keys, checked
Does the JWT signing key (asymmetric) expire?
Supabase's docs don't say whether the JWT signing key (asymmetric) expires.
What breaks when the JWT signing key (asymmetric) expires
Supabase documents no expiry date for signing keys. Revoking too early means your application no longer trusts any JWT signed with that key, so signed-in users are signed out and apps or Edge Functions still verifying against the legacy secret break. Revoking immediately is possible during an active security incident, at the cost of signing out active users.
How to rotate the Postgres database password
- Update the postgres role password from the Database Settings page in the Dashboard. Supabase docs
- Update any external service that connects with a hardcoded username and password. Supabase-managed services such as PostgREST and the dedicated pooler are updated automatically. Supabase docs
Can the old and new key work at the same time? Supabase's docs don't say. The docs do not say whether the old password keeps working after a change.
Revoking the old one: The docs describe no separate revoke step; changing the password is the documented way to replace it, and they do not say whether the old password stops working at once.
Source: supabase.com/docs/guides/database/managing-passwords, checked
Does the Postgres database password expire?
Supabase's docs don't say whether the Postgres database password expires.
What breaks when the Postgres database password expires
Supabase documents no expiry for the database password. Supabase says changing it causes no downtime, but external services with a hardcoded password must be updated by hand and will fail to connect until then; the docs give no error text.
How to rotate the Management API personal access token (sbp_)
- Open the access tokens page of your account in the Dashboard (/dashboard/account/tokens) and generate a new token. Prefer a scoped token limited to the organizations, projects and permissions you choose. Supabase docs
- Set an expiry when creating it: a preset duration, a custom date up to one year out, or never expire. Supabase docs
- Replace the old token wherever it is used (for example CI). A token's scope and permissions can't be edited after creation, so to change them create a replacement token. Supabase docs
- Delete the old token once nothing uses it. The changelog says token usage is tracked (updated up to every 15 minutes), which makes unused tokens easier to identify and remove. Supabase docs
Can the old and new key work at the same time? Yes. Supabase says every existing token works until it expires or you delete it, so the old and new token can both work during the switch.
Revoking the old one: Delete the old token from the same page. The docs say tokens work until they expire or are deleted but do not describe the delete steps.
Source: supabase.com/changelog/38248-personal-access-tokens-expiration-usage-tracking, checked
Does the Management API personal access token (sbp_) expire?
It's up to you: you can set an expiry for the Management API personal access token (sbp_).
What breaks when the Management API personal access token (sbp_) expires
A token with an expiry stops working at that date, and CI migrations or key provisioning that use it will start failing. The docs give no error text or status code, and do not mention expiry reminders. Tokens set to never expire do not lapse.
Each credential
Management API personal access token (sbp_)
- You choose
- Can be scoped
Expiry is set at creation: preset durations, a custom date up to 1 year out, or never expire (per Supabase changelog). Tokens created in the dashboard are scoped by default (scope fixed at creation, bounded by the creator's access); a legacy full-access option remains. Usage tracking shows last activity. Tokens can be given the API Keys permission, and OAuth scopes secrets:read and secrets:write are the equivalent for OAuth apps. Tokens are shown once. OAuth2-issued tokens are short-lived.
Legacy anon key (JWT)
- Doesn't expire
A JWT signed by the legacy JWT secret. Supabase says legacy keys are no longer recommended. Retiring a legacy key deactivates it rather than deleting it. Clients still using it must move to a publishable key; re-enabling a retired key restores its exposure. Supabase docs say legacy keys stay valid until you disable them in Settings > API Keys; Supabase says it is deprecating anon and service_role keys by the end of 2026.
Legacy service_role key (JWT)
- Doesn't expire
Bypasses row-level security. If leaked, retire it and also revoke the legacy JWT secret, because the key is a JWT signed by that secret. Revoking the legacy JWT secret is blocked until about 1 hour 15 minutes after the change, unless an active incident justifies revoking sooner. Supabase docs say legacy keys stay valid until you disable them in Settings > API Keys; Supabase says it is deprecating anon and service_role keys by the end of 2026.
Publishable key
- Not documented
Intended for browser and mobile clients. Not signed with the JWT signing key, so rotating JWT keys does not affect it, per Supabase docs. Format sb_publishable_...; not a JWT. The API keys page mentions no expiry or lifetime for new keys, so expiry stays unknown.
Secret key (server-side, non-JWT)
- Not documented
Created in the dashboard or with the Management API api-keys endpoint. Deleting a secret key is permanent and cannot be undone. Replace it rather than deleting it while clients still use it. Format sb_secret_...; not a JWT. The API keys page mentions no expiry or lifetime for new keys, so expiry stays unknown.
JWT signing key (asymmetric)
- Not documented
- Full access only
New keys start as standby, then are rotated into use. Revoke the previous key only after regularly valid JWTs have expired. Most state changes are throttled for about 5 minutes. Each action is reversible except permanent deletion. Use the Migrate JWT secret button to import the legacy secret.
Postgres database password
- Not documented
- Full access only
A public GitHub discussion reports that a reset sometimes shows success without taking effect, so verify the new password after resetting.
Renewals and billing
- Supabase paid plan.
Each organization has its own subscription, billing cycle and invoices (dashboard). The Management API reference lists no invoice, spend or cost endpoint in the groups read. Per-project usage endpoints exist under Analytics (usage.api-counts, usage.api-requests-count, 30 requests per minute).
Where to find it in Supabase
- Open Supabase API keys (Settings > API Keys)
- Open Supabase backups (Database > Backups)
- Supabase backups guide
- Supabase API keys guide
What Supabase's docs don't say
We couldn't confirm these from official docs, so don't rely on them either way:
- Whether new publishable and secret keys ever expire (docs mention no expiry)
- Exact legacy key deprecation date (docs say only 'by the end of 2026')
- Preset expiry durations for personal access tokens and the default
- Whether key metadata or token expiry is readable through the API
- Scopes available for secret and publishable keys
- Database password reset steps and whether they are current
- Plan pricing, billing cadence and billing API availability
- Dashboard login/session policy
Rotating or replacing a Supabase key
The steps are the same for most providers: make the new key, deploy it everywhere the old one is used, check it works, then revoke the old one. Our guides walk through it:
Sources
- supabase.com/docs/guides/security/rotate-leaked-api-keys
- supabase.com/docs/guides/auth/signing-keys
- supabase.com/docs/guides/api/api-keys
- supabase.com/docs/reference/api/introduction
- supabase.com/changelog/38248-personal-access-tokens-expiration-usage-tracking
- supabase.com/blog/scope-your-personal-access-tokens
- supabase.com/docs/reference/api/v1-bulk-create-secrets
- supabase.com/docs/guides/functions/secrets
- supabase.com/docs/guides/platform/audit-logs
- supabase.com/docs/guides/platform/billing-faq
- supabase.com/docs/guides/platform/manage-your-subscription
- supabase.com/docs/guides/platform/billing-on-supabase
Related providers
Keep track of every Supabase key
StackHangar stores your Supabase keys in an encrypted vault, grouped by the product they belong to, warns you before they expire, and walks you through rotating them. We can't read your secrets.