67 docs indexed
How obleth keeps serving when Redis or ClickHouse are unavailable: the moka fallback cache, the telemetry WAL, and the fail-open vs fail-closed tradeoff.
One of obleth's core design goals is that a Redis or ClickHouse outage should not take down inference traffic. This is the fail-open behavior.
This page covers obleth's resilience to datastore outages (Redis, ClickHouse, Postgres). For resilience to upstream failures — per-request timeouts, retries with backoff, and failover across multiple endpoints — see Reliability & Failover.
Key resolution on the data plane reads two caches and never Postgres:
Bearer token → SHA-256 hash
→ moka (in-process, TTL=5min, cap=100k) ← zero network latency
→ Redis (sub-ms, shared across pods) ← shared, always fresh
→ miss on both = 401
Redis is warmed from Postgres when the gateway starts and rewritten on every config change, so Postgres stays the source of truth without ever sitting in front of a request.
The in-process moka cache means that even a total Redis outage doesn't break auth lookups for keys that were recently resolved. Keys stay valid in moka for 5 minutes after their last resolution. A key that is in neither cache is rejected — there is no Postgres fallback on the hot path.
The moka cache is kept up-to-date via Redis pub/sub invalidation: when a key is created, disabled, or has its tenant's weight changed via the Management API, a message is published to obleth:invalidate. Each pod's moka evicts the affected key on receipt.
OBLETH_FAIL_OPEN (default: true) governs the budget checks, not identity. What a Redis failure does depends on which lookup failed:
| Redis operation fails | fail_open=true (default) | fail_open=false |
|---|---|---|
| Key or model resolution (moka already missed) | 401 / 404 — the gateway will not invent an identity | same |
| Token-budget reserve and term gate | Warn, raise an alert, and continue without budget enforcement | 503 budget check failed |
| Post-completion budget reconcile | Warn and continue | Warn and continue |
| Response-cache lookup or store | Treated as a miss; the request proceeds to the upstream | same |
For production deployments handling real customer traffic, fail-open is the safer default — a Redis blip doesn't cause a customer-visible outage for keys that are already resolved. Token budget enforcement is bypassed temporarily, but requests are still served.
For strict budget enforcement scenarios where over-spend must never happen, set OBLETH_FAIL_OPEN=false to reject rather than over-serve.
OBLETH_FAIL_OPEN=true
ClickHouse is never on the request hot path. Usage records are sent to a bounded async channel (mpsc::Sender), and a background task batches them into ClickHouse every second.
If ClickHouse is unavailable:
fail_open=true, each failed batch is written as a new spill segment in a directory alongside OBLETH_WAL_PATH (default: ./obleth-telemetry.wal, segments in <path>.segments/).# Where to spill telemetry when ClickHouse is unavailable
OBLETH_WAL_PATH=/var/lib/obleth/telemetry.wal
Spill is capped at 256 MiB total across segments and 1,024 segments. New spill is refused past either limit — obleth never silently evicts older accounting to make room. When spill is refused (or the disk is full), the batch is dropped, an error is logged, and the dropped-record counter advances.
Monitor it via Prometheus: obleth_telemetry_dropped is the count of records dropped because they could be written neither to ClickHouse nor to the WAL. Any non-zero value means usage rows were lost.
401, because identity is never assumed. Fail-open only relaxes budget enforcement.OBLETH_FAIL_OPEN=false: requests that do resolve are additionally rejected 503 at the budget check.obleth_telemetry_dropped increments. The already-spilled records still replay.obleth_telemetry_dropped increments.fail_open=false with ClickHouse down: batches are not spilled at all; they are counted as dropped immediately.401 — fail-open does not cover identity.401. Restart the gateway (it warms Redis from Postgres at boot) or make any config write to re-sync.