Skip to content
Back to news
9/14/2026

Gateway Service Tokens Are Now Appendable Without a Redeploy

Internal gateway service tokens now live in the database, so adding or revoking one no longer requires a worker redeploy.

ai-gatewayinfrainternal

This one is infrastructure, not a feature you'll click on — but it fixes a real operational trap, so it's worth explaining plainly.

The problem it replaces

The AI Gateway's internal routing worker authenticates service-to-service callers (other pieces of the platform, not end users) against a token. Historically that meant a Worker secret holding a JSON map of caller name to token — and because a secret can't be read back and appended to, adding one more caller meant rewriting the entire map and redeploying. That's exactly how this map ended up on its fourth version already (SERVICE_TOKENS, _V2, _V3, _V4): each time the map needed a new entry, the safe move was a new secret rather than risking a caller silently dropping out of a hand-edited one.

That risk was real, not theoretical — this is the documented trap: editing the wrong secret map, or mistyping one entry while adding another, can silently drop an existing caller's access. It's why this repo's own convention became "add a new versioned secret" instead of "edit the existing one," and why a fifth version was one bad request away from happening again.

What changed

Service tokens now also live in a database table, which can be read from and appended to without exposing existing entries — so adding a new caller is an insert, and revoking one is flipping a revoked_at timestamp, neither requiring a worker redeploy. Critically, the four legacy secret maps are checked first, unconditionally, exactly as before — the database is only consulted for a token none of the four maps recognize. That ordering means this change can only add a caller; it cannot regress one that already works today.

What this doesn't do

It doesn't retire the four legacy secrets yet — that's a deliberate, separate migration, tracked by which callers are actually resolving through the new path versus the old maps. And the code's own guidance is explicit: don't add a fifth versioned secret to patch around this again. If the database table can't serve a need, that's a schema question, not another secret.