Skip to content
Back to blog

Stateless vs Stateful Architecture

CoreConceptJuly 17, 20268 min read

A shopping cart must remember items, so the product cannot be literally stateless. The useful design question is where that state lives. Keep the cart inside one web server and the load balancer must keep finding that server. Move it to a shared store and any web server can handle the next request—but the shared store becomes a consistency and availability dependency.

This guide follows cart cart-42: a user adds an item, the application instance fails, and the next request lands on another instance. We will separate stateless protocol behavior from application state, trace both architectures, reproduce a sticky-session data-loss failure, and choose state placement from identity, consistency, latency, and recovery requirements.

Stateless vs stateful asks where continuity lives, not whether state exists
Stateless vs stateful asks where continuity lives, not whether state exists

State always has an owner

State is information whose current value depends on earlier events: cart items, session identity, database rows, offsets, locks, and workflow progress. HTTP is stateless because one request does not inherently depend on a previous request, but cookies and application stores can link requests into a stateful session.

A stateless application instance does not depend on its own local memory or disk between requests. The request carries enough identity (for example, session cookie sid=cart-42) for any instance to retrieve required state from an external store. A stateful instance retains session or domain state locally and therefore has an identity that later work must find again.

The whole system is rarely stateless. “Make it stateless” normally means make compute replaceable and move durable/shared state behind an explicit contract. That improves routing and replacement while adding network calls and a shared dependency.

Every stateful value needs an owner, lookup path, consistency rule, and failure plan
Every stateful value needs an owner, lookup path, consistency rule, and failure plan

Quick reference

  • State = information derived from prior events.
  • HTTP is stateless but applications can create sessions with cookies.
  • Stateless compute externalizes state; it does not erase it.
  • Stateful instances need stable identity, storage, or request affinity.
  • Ask: who owns state, how is it located, and what happens when that owner fails?

Remember this

Stateless compute does not remove state—it makes instances replaceable by moving state behind an explicit shared contract.

Stateless compute: any instance can serve the request

In the stateless version, the browser sends a secure session identifier with POST /cart/items. The load balancer chooses any healthy API replica. That replica validates the session, reads cart-42 from Redis or a database, applies the update atomically, and returns the new cart. No replica needs the previous request in local memory.

This design makes horizontal scaling and rolling replacement straightforward: add replicas and the load balancer gets more interchangeable targets; remove one and no session disappears with it. The trade is one or more remote state calls per request. Latency, connection pools, cache consistency, and shared-store availability now sit on the request path.

Do not put sensitive mutable cart state directly in an unsigned client payload. A cookie should usually contain an opaque session ID (with Secure, HttpOnly, and appropriate SameSite) or a signed token whose trust and revocation limitations are understood. The server still authorizes every cart operation.

Stateless request: any API replica uses the session ID to load cart-42 from shared state
Stateless request: any API replica uses the session ID to load cart-42 from shared state

Quick reference

  • Any healthy replica can handle any request.
  • Shared store owns session/cart consistency and lifetime.
  • Remote reads add latency and make pool sizing operationally important.
  • Use atomic updates or version checks for concurrent cart writes.
  • Secure session cookies identify state; they do not replace authorization.

Remember this

Stateless replicas scale and fail over cleanly because the request identifies state stored elsewhere; the shared store becomes the new critical dependency.

Stateful instances: identity and storage move with the worker

In the stateful version, API instance A keeps cart-42 in process memory. The next request must return to A, commonly through load-balancer session affinity (sticky sessions). This can reduce remote reads and ease migration of legacy applications, but A is no longer interchangeable with B.

If A fails, its memory disappears and the sticky mapping cannot help. Uneven session sizes can also create hotspots: one instance accumulates heavy users while another sits idle. Scaling down requires draining sessions or accepting loss. Replicating local state between instances can repair some of this, but now you are building a distributed state store inside the application tier.

Some workloads are legitimately stateful: databases, consensus members, stream processors with local checkpoints, and game servers with active matches may need stable identity and storage. In Kubernetes, StatefulSets provide stable network identity, ordinal names, and persistent volume association; they do not make the application's replication or failover semantics correct automatically.

Stateful request: affinity routes cart-42 back to the only instance holding its memory
Stateful request: affinity routes cart-42 back to the only instance holding its memory

Quick reference

  • Sticky sessions route a client back to the same instance.
  • Instance failure loses unreplicated memory state.
  • Affinity can create uneven load and complicate scale-down.
  • StatefulSet supplies stable identity/storage, not database correctness.
  • Use stateful workers when local ownership is part of the workload's semantics.

Remember this

Stateful instances make identity part of correctness: later work must find the same worker or its replicated storage.

One cart request through both designs

Compare the same second request after the user added a keyboard. With sticky local state, the load balancer reads its affinity cookie and routes to instance A; A reads its own memory and returns the cart. With external state, the load balancer may choose A, B, or C; the chosen replica reads cart-42 from the shared store.

The stateless path has an extra network dependency but a simpler compute failure boundary. The stateful path may be faster for a local read but needs affinity, draining, and a recovery story for A. “Faster” is therefore workload-dependent: measure remote-store latency against the cost of lost sessions, imbalance, and operational constraints.

Both designs still need concurrency control. Two tabs can add items at once. A local Map is safe only inside one process and still needs logic for conflicting updates; a shared store needs atomic commands, transactions, or compare-and-swap. State placement does not remove state semantics.

Same second cart request: route to the owner or look up shared state by key
Same second cart request: route to the owner or look up shared state by key

Quick reference

  • Same request, different lookup: affinity → local memory vs ID → shared store.
  • Stateless adds a network hop but removes compute identity from correctness.
  • Stateful local reads can be cheap while failover and draining become expensive.
  • Both paths need atomicity/versioning for concurrent updates.
  • Compare end-to-end p99 and recovery behavior, not one memory-access benchmark.

Remember this

The trade is local speed plus affinity versus a remote state call plus replaceable compute; concurrency control is required in both.

Failure story: the sticky target dies

Trigger. cart-42 is stored only in instance A's memory. A rolling deployment terminates A before sessions drain. Symptom: the next request reaches B, which returns an empty cart; infrastructure dashboards look healthy because B responds 200. Root mechanism: session affinity routed requests but never replicated state, so the routing target was also the only data owner.

Recovery. Stop the rollout, keep the old instance pool alive where possible, and communicate that affected carts may need rebuilding. Do not pretend an empty cart is a successful recovery. Prevention: externalize cart state to a durable/shared store, or replicate/checkpoint it with an explicit loss window. During migration, drain sticky sessions before termination and instrument “session not found” as an error rather than a normal empty state.

The opposite failure matters too: externalizing sessions to Redis makes all replicas dependent on Redis. If it fails, blindly retrying can create a storm. Use bounded timeouts, circuit breaking, and a product decision: return 503, serve a signed read-only snapshot, or allow anonymous browsing without cart mutation.

Sticky-session failure: healthy replacement responds but the local cart is gone
Sticky-session failure: healthy replacement responds but the local cart is gone

Quick reference

  • Trigger: terminate the only instance holding local cart state.
  • Symptom: healthy 200 from another replica with an empty cart.
  • Mechanism: affinity preserved routing, not data.
  • Prevention: externalize/replicate state and drain before scale-down.
  • Shared-store outage needs bounded retries and an explicit degraded mode.

Remember this

Sticky routing is not state replication: when the target dies, a healthy replacement can return the wrong empty cart.

Scaling and security follow state placement

Stateless compute scales by adding interchangeable replicas, but the state store must scale with it. Watch store latency, hot keys, memory, connection count, eviction, replication lag, and durability policy. A single shared Redis with no failover simply moves the single point of failure.

Stateful workloads scale by partitioning ownership: shard users, rooms, or keys across stable workers, then route work to the owner. Rebalancing moves state and can pause or duplicate work; consistent hashing reduces movement but does not solve replication, ordering, or recovery. This is why scaling a database is not equivalent to adding web replicas.

Security also follows the owner. Local sessions vanish on restart but may expose secrets in process dumps. Shared stores centralize sensitive state and require encryption, network isolation, least privilege, TTLs, and audit. Client-carried tokens reduce server lookups but make revocation and claim freshness explicit trade-offs; never put mutable authoritative cart contents in a token just to call the server “stateless.”

Quick reference

  • Scale stateless compute independently, then capacity-plan the shared store.
  • Hot sessions/keys can bottleneck a shared store even with many API replicas.
  • Stateful scale requires ownership, partition movement, replication, and recovery.
  • Secure shared stores with identity, network policy, encryption, TTL, and audit.
  • Client tokens trade server lookups for revocation and stale-claim concerns.

Remember this

Moving state changes the bottleneck and trust boundary: replaceable APIs shift capacity, consistency, and security work to the state owner.

Choose by state semantics, not fashion

Prefer stateless application replicas for request/response APIs when any instance can reconstruct context from the request plus an external store. This is the default for horizontally scaled web tiers because replacement, rollout, and load balancing stay simple.

Use stateful workers when stable identity or local ownership is fundamental: databases, consensus nodes, ordered stream partitions, active game rooms, or large local working sets that cannot be reloaded per request. Then design placement, persistence, replication, failover, and rebalancing as first-class behavior.

Sticky sessions are a compatibility tool, not a durability mechanism. Use them temporarily for legacy local sessions or deliberately for locality, with draining and loss behavior documented. The decision rule is: place state where its consistency and recovery contract can be enforced, then make every other component replaceable.

Decision: use replaceable compute unless stable ownership is part of the workload
Decision: use replaceable compute unless stable ownership is part of the workload

Quick reference

  • Web/API compute → usually stateless replicas + external state.
  • Stable ownership/order/local working set → stateful worker with explicit recovery.
  • Sticky sessions → migration/locality tool, not replication.
  • Choose store consistency/durability from the actual cart contract.
  • Make non-owners disposable; test owner failure and state recovery.

Remember this

Place state where its consistency and recovery contract can be enforced; make the remaining compute interchangeable.

Key takeaway

Stateless and stateful describe where continuity lives, not whether the product remembers anything. Stateless API replicas move continuity into a shared store and become easy to replace. Stateful workers keep continuity with stable identity and must own persistence, routing, and recovery. Neither is automatically faster or safer—the state contract decides.

Practice (30 minutes): build a two-replica cart API. First store carts in a process Map, add load-balancer affinity, create cart-42, and terminate its owner; record the result. Then move the cart to Redis or a local shared database, remove affinity, and repeat. Finally stop the shared store and implement a bounded 503 response instead of infinite retries. You pass when the cart survives API replacement and the store failure produces an honest, controlled response.

Share:

Related Articles

An order API can return responses all day and still charge the wrong amount. It can be temporarily unreachable while eve

Read

A dashboard can look “fast” while users still wait, and a load test can report huge requests-per-second while p99 checko

Read

"Just use Postgres" is good advice until a measured access pattern needs a specialist. A checkout might use Redis for th

Read

Keep learning

Follow a structured path or browse all courses to go deeper.