Skip to content

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#

  1. 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.

  1. Read it back in your function with Deno.env.get() and JSON.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
  1. 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 jq rather 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.

Additional resources#