Per-environment Upstash databases (D17)
Current state
The cluster uses a shared Upstash Redis topology across environments. Develop, staging, and production all read and write to the same Upstash database. Per-environment and per-developer isolation is provided by ioredis's keyPrefix connection option (Environment.LOCAL → ${USER}:; deployed envs → empty).
The shared topology is operationally simple — one set of credentials, one dashboard, one set of capacity metrics — and the keyPrefix mechanism is centralized in redis.config.ts.
The deferred alternative
Provision a separate Upstash database per environment (and optionally per developer). Each environment connects to its own database; isolation is at the connection level rather than the key level.
Why deferred
- Per-env Upstash databases cost roughly $10/mo per database plus provisioning friction.
- The shared topology is centralized in one config file — moving to per-env is non-trivial but not architecturally complex.
- No isolation incident has materialized to justify the cost.
Known risks the shared topology carries
Documented in openspec/changes/add-multi-instance-runtime-readiness/design.md §D8:
Credential blast radius
A compromise of a developer's machine yields the dev Upstash credentials, which point at the same database production reads from. The prefix isolates keys, not the connection. An attacker with valid credentials could KEYS * against the database and read staging/production keys, or issue arbitrary commands as the connected user.
Database-level commands bypass the prefix
FLUSHDB, FLUSHALL, SCRIPT FLUSH etc. are connection-level, not key-level. A future contributor running FLUSHDB against their dev URL would wipe staging and production keys too. The codebase does not use these commands today and SHALL NOT add them in v0.6.0; if a flush operation ever becomes required, it must scan-and-delete by keyPrefix* pattern, never FLUSHDB.
Revisit trigger
Either:
- (a) A real isolation problem materializes — developer-machine compromise, accidental
FLUSHDB-class incident, performance noise from cross-environment workload, key-namespace exhaustion - (b) A routine security review concludes that the credential blast radius is unacceptable for the production data classification
When either trigger fires, per-env provisioning is the unblocker — the keyPrefix layer can stay as defense-in-depth.
Related
- OpenSpec:
openspec/current-decisions-for-future-tracking.md §D17,openspec/changes/add-multi-instance-runtime-readiness/design.md §D8 - Current state → Multi-instance runtime