Skip to main content

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.