skip to content

A team proposes moving server-side session data out of instance memory into a shared Redis cluster so the service can scale horizontally. Evaluate that choice against pushing the same context into self-contained requests, and say when you would pick each.

level: principalimportance: nice to knowfreq 35%

answer

  1. State must live somewhere: node, store, or request
  2. Store: instant revocation, correlated failure
  3. Request: no dependency, stale until expiry
  4. Scale-out multiplies connections to the store
  5. Hybrid: short-lived token + server-side refresh record

basics

~20 s

Redis restores any-instance routing but relocates the state rather than removing it: you gain instant revocation and small requests, and take on a shared dependency, a round trip per request, and a new failure and capacity domain. Self-contained requests remove that dependency but make revocation and payload size harder.

solid answer

~50 s

Both options restore interchangeable instances; they differ in **where the coupling lands**. A shared store keeps requests small, allows arbitrarily large or sensitive server-side context, and gives immediate invalidation - delete the key and the session is gone. Costs: a lookup on the hot path of every request, a component whose outage degrades all instances simultaneously, capacity that scales with connections during scale-out bursts, and cross-region latency if you ever go multi-region. Self-contained requests (a signed token plus explicit parameters) remove the per-request dependency entirely and survive a store outage, but the data is on the wire on every call, it is only as fresh as its expiry, and revoking before expiry needs its own mechanism. I would default to self-contained context with short lifetimes for large-scale, multi-region or public APIs, and pick a shared store when immediate revocation, large context, or regulatory control over the session record outweigh the dependency.

go deeper

for a junior

Recognise that both approaches let any instance serve any request; a shared store keeps the data server-side while a token carries it with the request.

for a middle

Contrast the round trip and dependency of a store against payload size and staleness of a token, and mention short lifetimes as the usual compromise.

for a senior

Argue from failure behaviour and revocation requirements, and describe the hybrid of short-lived credentials with a server-side refresh record.

for a principal

Set explicit decision criteria and thresholds, address multi-region topology, correlated failure, capacity coupling under scale-out, and state the fail-open versus fail-closed policy.

## Framing the decision The question is not whether Redis is allowed. It is that per-client context must live somewhere, and each placement buys and costs something different. There are three placements - the instance (rejected: it breaks interchangeability), a shared store, or the request itself. ## Shared store: what you buy **Instant invalidation.** Deleting the key ends the session on the next request, which matters for logout-everywhere, password change, employee offboarding and compromise response. **Unbounded, private context.** Whatever you keep - permissions, feature flags, cart contents, personal data - never crosses the wire and is not visible to the client. **Small requests.** Only a short opaque identifier travels, which keeps header sizes low and avoids repeatedly transmitting sensitive data. **Mutability.** State can change server-side between requests without the client re-authenticating. ## Shared store: what you pay **A synchronous dependency on the hot path.** Every authenticated request now includes a store round trip. Sub-millisecond in-datacentre, but it is a hard dependency: if the store is slow, every endpoint is slow. **Correlated failure.** The store's failure is not partial - it degrades all instances at once. It needs replication, failover testing, sensible client timeouts, and a decided behaviour on outage (fail closed and reject, or fail open on cached decisions and accept the security consequence). **Capacity coupling to scale-out.** When autoscaling triples the instance count under load, connection pools triple against the store precisely when it is busiest. Pool sizing and connection limits become a real capacity plan, not a config default. **Geography.** In a multi-region deployment the store is either replicated (with consistency and conflict questions) or remote for some regions (with latency on every request). This is often the argument that ends the debate at large scale. **Operational surface.** Persistence settings, eviction policy, memory sizing, upgrades, and the classic failure of an eviction policy silently expiring live sessions under memory pressure. ## Self-contained requests: what you buy and pay Putting context in the request - a signed token carrying identity and claims, plus explicit parameters carrying position and filters - eliminates the lookup and the dependency. Instances validate locally; the service keeps working when the store is down, because there is no store. It scales and regionalises trivially. The costs are real. Every request carries the payload, so header size grows and large claim sets get expensive across many small calls. The data is a **snapshot**: a permission revoked centrally stays effective until the token expires, so you trade freshness for independence. Anything sensitive is visible to the holder unless encrypted. And revoking before expiry requires reintroducing a lookup - a denylist or version check - which partially reintroduces the dependency you removed. ## How I would actually decide **Choose self-contained when**: the API is public or high-volume, latency budgets are tight, the deployment is multi-region, the context is small and slow-changing, and a revocation delay of a few minutes is acceptable. **Choose a shared store when**: revocation must be immediate and auditable, context is large or must never reach the client, sessions are browser-based with server-rendered flows, or a regulator requires server-side control over the session record. **A common hybrid**: short-lived self-contained access credentials (minutes) for the hot path, plus a server-side record for the long-lived refresh credential. Ordinary requests need no lookup; revocation lands within one short lifetime; and the store is consulted only on refresh, so its traffic is orders of magnitude lower and an outage degrades logins rather than the whole API. ## What makes the answer senior-plus Naming the decision criteria and their thresholds, stating the failure behaviour explicitly (fail open versus fail closed), and acknowledging that neither option is stateless in the naive sense - one moves state sideways, the other moves it outward.

  • What should the API do when the shared session store is unavailable?
    Decide deliberately and document it. Failing closed rejects authenticated traffic and turns a store outage into a full outage; failing open on a cached decision keeps traffic flowing but extends the window in which revoked access still works. Most teams fail closed for privileged operations and allow a short cached grace period on read-only paths, with aggressive timeouts so requests do not queue behind a hanging store.
  • How would you get near-immediate revocation without a lookup on every request?
    Keep credentials short-lived so expiry itself bounds the damage, and push revocation into the far less frequent refresh path. Where faster is needed, add a small denylist of revoked identifiers replicated to each instance and consulted locally - it stays tiny because entries can be dropped once the credential would have expired anyway.

saying these in an interview costs you the question

  • Calling a Redis-backed session design fully stateless rather than relocated state
  • Ignoring that every authenticated request now depends on the store's availability and latency
  • Not planning connection-pool growth when autoscaling multiplies instances
  • Assuming self-contained tokens make revocation impossible rather than delayed and bounded
  • Putting large or sensitive context into a client-held token because it removes the database

context