Working around the Edge Function secrets limit
Last edited: 9/15/2026
Edge Functions projects are capped at 100 secrets (see Functions limits). If you're managing credentials for many third-party services, you can hit this cap even though you haven't done anything wrong — each supabase secrets set NAME=VALUE call uses one slot, regardless of how small the value is.
Supabase doesn't raise this limit on a per-project basis today. The workaround below gets around it — though the per-secret size limit below still applies, so it isn't a way around every constraint.
How to fix#
- Group related credentials into a JSON object and store it under a single secret name:
supabase secrets set API_KEYS='{"stripe":"sk_live_xxx","sendgrid":"SG.xxx","aws":"xxx"}'This counts as one secret against the 100 limit, no matter how many keys are nested inside it.
- Read it back in your function with
Deno.env.get()andJSON.parse:
const raw = Deno.env.get('API_KEYS')if (!raw) { throw new Error('Missing API_KEYS secret')}const keys = JSON.parse(raw)const stripeKey = keys.stripe- Confirm it was set with
supabase secrets list.
This is the same pattern Supabase's own default secrets use — SUPABASE_PUBLISHABLE_KEYS and SUPABASE_SECRET_KEYS are themselves JSON dictionaries parsed the same way (see Environment Variables).
Things to watch for#
- No partial updates. Setting a new value replaces the whole secret, so updating one key means re-setting the entire JSON blob. Build the JSON with a script or
jqrather than hand-typing it — a single typo breaks every key in the group. - Quoting on the command line gets messy fast, especially outside bash/zsh (e.g. Windows shells don't handle single-quote literals the same way). If that happens, load the secret from a file instead — the value isn't parsed by the shell, which sidesteps the escaping problem:
supabase secrets set --env-file .env
- Secrets are capped at 48 KiB (24,576 characters) (Functions limits). Group logically — for example, one secret per third-party integration — rather than merging everything into a single blob. Typical API keys (tens to a couple hundred characters) leave plenty of headroom; long-lived tokens, JWTs, or certificates can approach the size cap with only a handful of entries.
When this isn't the right fit#
Consider Supabase Vault when your values vary by row, such as secrets tied to individual users or organizations. Vault stores encrypted secrets in Postgres, and the 100-secret limit doesn't apply.
Reading a Vault secret from an Edge Function costs a database round-trip, either supabase.rpc() against a security definer function or a service-role query. That adds latency.
For a flat list of project-wide credentials, grouping them into a single JSON secret avoids the round-trip.