Redis Keys¶
Redis is the gateway's fast mutable state store. PostgreSQL remains the durable source of truth for keys, policy, service registration, usage records, and operator state. Redis stores only short-lived rate-limit and budget control state plus readiness checks.
Scope¶
REDIS_URLpoints Gateway at the Redis instance used for readiness, rate limits, and budget counters./admin-ui/readyzchecks Redis withPING; readiness does not create a persistent application key.- Redis keys are generated by
gateway-corehelpers and written bygateway-store::RedisControlState. - All current keys are scoped by the PostgreSQL
api_keys.idUUID, not by raw virtual key material or key prefixes.
Required Operational State¶
| Area | Redis key family | Required when |
|---|---|---|
| Request rate limit | rl:req:<key_id>:<yyyymmddhhmm> |
A virtual key policy has rpm_limit set. |
| Token rate limit | rl:tpm:<key_id>:<yyyymmddhhmm> |
A virtual key policy has tpm_limit set. |
| Daily budget | budget:daily:<key_id>:<yyyymmdd> |
A virtual key policy has a daily budget or a request records/reserves positive cost. |
| Monthly budget | budget:monthly:<key_id>:<yyyymm> |
A virtual key policy has a monthly budget or a request records/reserves positive cost. |
| Budget reservation | budget:reservation:<key_id>:<request_id> |
A request reserves estimated cost before final usage reconciliation. |
Redis can be treated as volatile for normal operations. Restarting or flushing Redis clears rate-limit windows, budget counters, and in-flight budget reservations, but does not delete virtual keys, policies, usage events, or operator state from PostgreSQL.
For budgeted keys, Gateway rebuilds current daily and monthly budget counters from PostgreSQL usage events during startup after Redis readiness succeeds, and continues periodic reconciliation while the process runs. PostgreSQL remains the durable billing ledger; Redis is reconstructed control state.
Key Reference¶
rl:req:<key_id>:<yyyymmddhhmm>¶
Request-per-minute counter for one virtual key and one UTC minute.
| Field | Details |
|---|---|
| Example | rl:req:018f8d31-86a7-7c48-8f36-4d1fa4d99101:202605091403 |
| Owner | RateLimitStore::check_request_rate_limit. |
| Value | Integer counter incremented with INCR. |
| Time bucket | UTC minute formatted as YYYYMMDDHHMM. |
| TTL | 70 seconds. |
| Created when | key_policies.rpm_limit is not NULL and the key makes a request. |
| Used for | Comparing the incremented count with rpm_limit; exceeded requests return retry timing based on Redis TTL when available. |
The 70-second TTL intentionally outlives the exact minute boundary so late requests and clock skew do not immediately erase the active bucket.
rl:tpm:<key_id>:<yyyymmddhhmm>¶
Token-per-minute counter for one virtual key and one UTC minute.
| Field | Details |
|---|---|
| Example | rl:tpm:018f8d31-86a7-7c48-8f36-4d1fa4d99101:202605091403 |
| Owner | RateLimitStore::check_token_rate_limit. |
| Value | Integer counter incremented with INCRBY using the gateway's estimated request token impact. |
| Time bucket | UTC minute formatted as YYYYMMDDHHMM. |
| TTL | 70 seconds. |
| Created when | key_policies.tpm_limit is not NULL and the key makes a request with a positive token estimate. |
| Used for | Comparing the incremented token estimate with tpm_limit; exceeded requests return token_rate_limit_exceeded and retry timing based on Redis TTL when available. |
TPM enforcement uses preflight token estimates so Gateway can reject traffic before forwarding it upstream. Final provider usage is still recorded in PostgreSQL usage events.
budget:daily:<key_id>:<yyyymmdd>¶
Daily spend counter for one virtual key and one UTC day.
| Field | Details |
|---|---|
| Example | budget:daily:018f8d31-86a7-7c48-8f36-4d1fa4d99101:20260509 |
| Owner | BudgetStore::check_budget, add_budget_spend, reserve_budget, reconcile_budget_reservation, and release_budget_reservation. |
| Value | Floating-point USD amount stored through INCRBYFLOAT. Missing or unparsable values are treated as 0.0 by Gateway. |
| Time bucket | UTC day formatted as YYYYMMDD. |
| TTL | 172,800 seconds, or 2 days, after writes that add or reserve positive spend. |
| Created when | A positive estimated or actual cost is recorded or reserved for the key. |
| Used for | Enforcing key_policies.daily_budget_usd and reporting the current daily budget state during checks. |
When a request reserves budget, this counter is incremented immediately. Later reconciliation adjusts it by the difference between actual cost and reserved cost. Releasing a reservation subtracts the reserved amount.
budget:monthly:<key_id>:<yyyymm>¶
Monthly spend counter for one virtual key and one UTC month.
| Field | Details |
|---|---|
| Example | budget:monthly:018f8d31-86a7-7c48-8f36-4d1fa4d99101:202605 |
| Owner | BudgetStore::check_budget, add_budget_spend, reserve_budget, reconcile_budget_reservation, and release_budget_reservation. |
| Value | Floating-point USD amount stored through INCRBYFLOAT. Missing or unparsable values are treated as 0.0 by Gateway. |
| Time bucket | UTC month formatted as YYYYMM. |
| TTL | 5,356,800 seconds, or 62 days, after writes that add or reserve positive spend. |
| Created when | A positive estimated or actual cost is recorded or reserved for the key. |
| Used for | Enforcing key_policies.monthly_budget_usd and reporting the current monthly budget state during checks. |
The 62-day TTL keeps the current and recently closed monthly bucket available long enough for late reconciliation.
budget:reservation:<key_id>:<request_id>¶
In-flight budget reservation for a single request.
| Field | Details |
|---|---|
| Example | budget:reservation:018f8d31-86a7-7c48-8f36-4d1fa4d99101:req-1 |
| Owner | BudgetStore::reserve_budget, reconcile_budget_reservation, and release_budget_reservation. |
| Value | Pipe-delimited string: <amount_usd>|<daily_key>|<monthly_key>. |
| TTL | 3,600 seconds, or 1 hour. |
| Created when | Gateway reserves a positive estimated cost for a request. |
| Deleted when | Reconciliation applies actual cost, or release subtracts the reservation after failure/cancellation. |
| Fallback behavior | If the reservation key is missing or malformed, Gateway treats the reserved amount as 0.0 and derives the daily/monthly keys from the current request context. |
Reservation values include the original daily and monthly budget keys so reconciliation can adjust the same time buckets that were charged during reservation, even if the request crosses a UTC day or month boundary.
Operating Notes¶
- Do not store raw Relayna virtual keys, operator tokens, provider credentials, prompts, or request bodies in Redis.
- Use PostgreSQL usage events for durable billing and audit history. Redis budget counters are control-plane state, not the billing ledger.
- A Redis flush no longer requires manually rebuilding daily or monthly budget spend for keys with configured budgets; Gateway rehydrates current counters from PostgreSQL after Redis readiness succeeds. In-flight reservations cannot be reconstructed and should be allowed to expire or be reconciled by the request that created them.
- Avoid manual edits unless recovering from a known operational incident. If a
counter must be corrected, update both the daily and monthly counter for the
same
key_idconsistently. - Redis persistence is optional for basic gateway operation. Enable Redis persistence only when your deployment requires rate-limit and budget state to survive Redis restarts.