# Working around the Edge Function secrets limit

Edge Functions projects are capped at **100 secrets** (see [Functions limits](https://supabase.com/docs/guides/functions/limits#secrets)). 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:

```bash
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.

2. Read it back in your function with `Deno.env.get()` and `JSON.parse`:

```typescript
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
```

3. 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](https://supabase.com/docs/guides/functions/secrets#accessing-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:
  ```bash
  supabase secrets set --env-file .env
  ```
- **Secrets are capped at 48 KiB (24,576 characters)** ([Functions limits](https://supabase.com/docs/guides/functions/limits#secrets)). 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](https://supabase.com/docs/guides/database/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](#how-to-fix) avoids the round-trip.

## Additional resources

- [Functions limits — Secrets](https://supabase.com/docs/guides/functions/limits#secrets)
- [Environment Variables — accessing and setting secrets](https://supabase.com/docs/guides/functions/secrets)
- [Supabase Vault](https://supabase.com/docs/guides/database/vault)
