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.

Last checked 2026-11-08 · supabase.com

At a glance

CredentialExpiryPermissions
Management API personal access token (sbp_)You chooseCan be scoped
Legacy anon key (JWT)Doesn't expireNot documented
Legacy service_role key (JWT)Doesn't expireNot documented
Publishable keyNot documentedNot documented
Secret key (server-side, non-JWT)Not documentedNot documented
JWT signing key (asymmetric)Not documentedFull access only
Postgres database passwordNot documentedFull access only

How to rotate the Legacy service_role key (JWT)

  1. 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
  2. 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
  3. 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
  4. 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
  5. Replace the legacy anon key with a publishable key in browser and mobile clients. Supabase docs
  6. 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
  7. Deactivate the legacy keys in Settings > API Keys. This is reversible. Supabase docs
  8. 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:

How to rotate the Legacy anon key (JWT)

  1. In Settings > API Keys, open the "Publishable and secret API keys" tab and create a publishable key. Your legacy keys keep working. Supabase docs
  2. 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
  3. 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
  4. 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)

  1. 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
  2. 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
  3. 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)

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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

  1. Update the postgres role password from the Database Settings page in the Dashboard. Supabase docs
  2. 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_)

  1. 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
  2. Set an expiry when creating it: a preset duration, a custom date up to one year out, or never expire. Supabase docs
  3. 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
  4. 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_)

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.

Supabase docs

Legacy anon key (JWT)

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.

Supabase docs

Legacy service_role key (JWT)

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.

Supabase docs

Publishable key

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.

Supabase docs

Secret key (server-side, non-JWT)

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.

Supabase docs

JWT signing key (asymmetric)

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.

Supabase docs

Postgres database password

A public GitHub discussion reports that a reset sometimes shows success without taking effect, so verify the new password after resetting.

Renewals and billing

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

What Supabase's docs don't say

We couldn't confirm these from official docs, so don't rely on them either way:

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

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.