Enforcement, Fail Modes, and Availability
How Athena decides whether a route requires keys, and what happens when the auth store is down.
Gateway key enforcement is not a single boolean. Athena combines config, per-client overrides, hot-path cache behavior, and auth-store availability.
Where the auth store lives
gateway.auth_client selects the Postgres client used for:
- key lookup
- rights loading
- IP policy loading
- auth configuration tables like
api_key_configandapi_key_client_config
If gateway.auth_client is unset, Athena falls back to gateway.logging_client.
Global enforcement vs per-client overrides
Athena resolves enforcement like this:
- load the global value from
api_key_config - if the request names a client and
api_key_client_confighas an override for that client, use the override - otherwise use the global value
This lookup is exposed through get_effective_api_key_enforcement.
Request-time decision path
Status code map
| Condition | Typical response |
|---|---|
| Missing key while enforcement is on | 401 |
| Invalid format or secret mismatch | 401 |
| Inactive key | 401 |
| Expired key | 401 |
| Client mismatch | 403 |
| Missing rights | 403 |
| IP blocked or not whitelisted | 403 |
Auth store unavailable with fail_closed | 503 |
Policy lookup unavailable with fail_closed | 503 |
Fail modes
gateway.api_key_fail_mode supports two values:
| Mode | Behavior |
|---|---|
fail_closed | reject protected requests when the auth store or policy lookup is unavailable |
fail_open | allow requests through when the auth store or policy lookup is unavailable |
Athena defaults to fail_closed, which is the safer production choice.
fail_open is an availability tradeoff, not a security best practice. Use it
only when you understand that protected routes may continue without key
enforcement during auth-store failures.
Hot-path cache behavior
Athena caches a few auth decisions for about two seconds:
- effective enforcement
- per-key IP policy
- global IP rule sets
Useful implementation details:
- the enforcement cache can serve stale values when the store lookup fails
- per-key and global IP caches are invalidated by admin mutations
- enforcement config changes rely on the short TTL rather than an explicit invalidation hook
Control plane vs data plane auth
The lifecycle routes in src/api/admin/mod.rs use authorize_static_admin_key,
which accepts:
X-Athena-Key: $ATHENA_KEY_12X-Athena-Admin-Key: $ATHENA_KEY_12
Runtime gateway auth in src/api/auth.rs currently extracts only:
X-Athena-Key: ath_{public}.{secret}
That means a gateway key can authorize a protected runtime route, but it cannot
create or edit other keys through /admin/*.
Availability failures and pool starvation
When the auth store shares a saturated Postgres pool with logging, callers may see:
API key validation unavailableAPI key policy unavailablepool timed out while waiting for an open connection
That incident pattern is explained in Gateway Pool Starvation And Auth Failures.