LearnastraTHE DESIGN COURSE

Make the right trade-off / CHAPTER 33

Stateful versus stateless architecture

Choose where carts, sessions and connection progress live so another worker can recover them after a failure.

Beginner1h of deliberate study10 questions

Builds on Caching fundamentals, Load balancing.

By the end, you can
  • Identify state and its owner.
  • Explain stateless workers without claiming the whole system has no state.
  • Plan recovery for sessions and live connections.

01Stateless means independent request handling

A shopper sends two requests: first add a book to a cart, then display the cart. Ask where the information from the first request lives.

  • Stateful worker: worker A keeps the cart in its own memory, and the later request depends on reaching A or recovering that memory elsewhere.
  • Stateless request worker: each request identifies the user and cart. Either worker A or B can load the saved cart; neither needs history kept only in its own process from an earlier request.

“Stateless” does not mean the application has no data. Accounts, carts, orders and permissions still exist in persistent stores. It describes how a particular request-handling layer depends on local history.

Different information has different loss consequences. A product-cache copy can be rebuilt from the database. Losing the only saved purchase record loses a business fact. A live network connection is temporary again: its failure requires reconnection even when all messages remain safely stored.

02Find the recovery boundary

Plan recovery by following each kind of information:

Information Where might it live? What happens when a worker fails?
Variables for one request That worker's memory. Fail or safely retry the request.
Saved cart and version A shared persistent cart store. Another worker reloads it.
Product cache Replaceable worker memory. Rebuild it from the product source.
Login session Shared session storage or a defined signed-token design. Verify identity and the chosen expiry/revocation rules.
Live connection The connection server. Reconnect, then recover application progress separately.

For ordinary cart requests:

  1. The client identifies the cart and authenticates. A user token names the caller; it does not recreate missing cart contents.
  2. Any eligible worker loads the saved cart. Shared storage adds latency and a failure dependency, but makes history recoverable outside one process.
  3. The worker checks concurrent changes before writing. Sharing a location does not prevent two workers overwriting each other's edits.

Some operations benefit from one stateful worker. A game-room server can apply moves locally in order. Save its accepted moves or checkpoints so a replacement can reload them. Give each replacement a new writer-permission number; the game store must check that number together with saving a move, and reject the old worker’s number. A worker reports acceptance only after that guarded save succeeds.

Sticky routing only sends the client back to the same worker. It neither saves a checkpoint nor copies memory to a replacement.

03Worked example: cart and chat connection

Cart 42 contains one item at version 7. Follow two devices:

  1. The phone asks worker A to add a book. A reads version 7.
  2. A browser tab asks worker B to remove the original item. B also reads version 7.
  3. A saves its change as version 8. If B blindly replaces the whole cart using its old copy, B can erase the new book.
  4. B submits a conditional update: replace the cart only if its saved version is still 7. The store compares and changes the record in one indivisible operation. Because it now holds 8, B's update conflicts instead of silently overwriting it.
  5. B reloads the cart. After reloading, it can apply the tab’s explicit instruction to remove the original item while preserving the newly added book. If an edit cannot be reapplied without guessing the user’s intent, ask the user to resolve it. A later request can reach either worker and load the saved result.

For chat, recovery is different

  1. The message service saves accepted text in persistent history. The client saves its last applied message position only after it has saved the corresponding messages locally.
  2. A WebSocket server fails, ending its persistent two-way connection.
  3. The client connects to another server, authenticates and asks for messages after its saved position. The old connection itself does not migrate.

Signed tokens can avoid a session lookup on every request. Their signature proves issued content was not changed, not that an hour-old permission is still current. Define token lifetime, signing-key changes and any current revocation lookup before claiming immediate permission updates.

Stateful versus stateless architecture — decision flow

Stateful versus stateless architecture — decision flowThe request identifies the saved cart and the version the client edited. Either worker loads the cart; an update succeeds only if the saved expected version still matches. Another worker can recover persistent records after replacement; lost private process memory is not a recovery source. Numbered arrows correspond to the connection key below. All connections are directional.Shopper phone andtabCart 42; expectedversion 7Worker APhone commits version8Worker BOld version must notoverwriteCart databaseSaved cart contentsand current version1234Stateful versus stateless architecture — decision flowThe request identifies the saved cart and the version the client edited. Either worker loads the cart; an update succeeds only if the saved expected version still matches. Another worker can recover persistent records after replacement; lost private process memory is not a recovery source. Numbered arrows correspond to the connection key below. All connections are directional.Shopper phone andtabCart 42; expectedversion 7Worker APhone commits version8Worker BOld version must notoverwriteCart databaseSaved cart contentsand current version1234Stateful versus stateless architecture — decision flowThe request identifies the saved cart and the version the client edited. Either worker loads the cart; an update succeeds only if the saved expected version still matches. Another worker can recover persistent records after replacement; lost private process memory is not a recovery source. Numbered arrows correspond to the connection key below. All connections are directional.Shopper phone andtabCart 42; expectedversion 7Worker APhone commits version8Worker BOld version must notoverwriteCart databaseSaved cart contentsand current version1234

Follow the numbered arrows

  1. Shopper phone and tab → Worker Athe phone reaches worker A
  2. Shopper phone and tab → Worker Bthe tab reaches worker B
  3. Worker A → Cart databaseread or conditionally update the cart
  4. Worker B → Cart databaseread or conditionally update the cart
Either worker can read the same saved cart. A version condition rejects a stale replacement instead of overwriting another device’s edit.
Trace the diagram in words
  1. The request identifies the saved cart and the version the client edited.
  2. Either worker loads the cart; an update succeeds only if the saved expected version still matches.
  3. Another worker can recover persistent records after replacement; lost private process memory is not a recovery source.

04Choose state placement intentionally

Choose placement for a stated benefit:

  • Stateless workers: use them when requests can recover required records independently, making routing, replacement and fleet changes simpler.
  • Stateful workers: use them when keeping related work together has a measured benefit, such as one ordered game simulation. Explain how a replacement loads progress and prevents old-owner writes.
  • Removing a stateful worker: stop new assignments, finish or save work, transfer responsibility safely, then reconnect clients. Do not start a second conflicting game owner.
  • Removing a stateless worker: drain accepted requests; other workers recover saved history from its store.
  • Retried purchases: statelessness alone is insufficient. Save the request key and purchase result together. Worker B can then return A's existing result after a lost response rather than buying again.

Evaluate response time, store load, session recovery and correctness separately. Calling a layer stateless is not proof that every required record survives a failure.

DRAW. CALCULATE. EXPLAIN.

Move a cart between workers

20 minutes · guided practice

A keeps a cart in memory at version 12. You add B and later remove A. Two tabs can modify the cart concurrently, and an acknowledged purchase may be retried. Design state placement, transition and conflict handling.

Your self-check
Compare the worked solution
  1. Move the cart from A's private memory into persistent storage accessible to B before routing independently. For a simple move, pause cart edits, save the latest cart and version in shared storage, switch both workers to that store, then resume edits. Otherwise an edit arriving during copying could be lost.
  2. Each update supplies the version it read. If two tabs read 12 and one commits 13, the other must conflict, reload or merge under a defined rule.
  3. Stop new routing to A and finish or safely retry its accepted work before removal.
  4. Save a purchase's request ID and result with the purchase change. A retry on B looks up that record and returns the original result instead of creating another purchase.

The checkboxes record your own assessment. The worked solution gives you a way to check the reasoning.

RETRIEVE BEFORE YOU REVEAL

Keep the important ideas.

Say the answer aloud, then turn the card over.

CARD 01What makes a request worker stateless?
  1. Requests identify the user and resource.
  2. Required history is saved outside that worker’s private memory.
  3. Another worker can load it and continue; the system still has accounts, carts and other state.
CARD 02Why does a shared cart store need conflict checks?
  1. Two workers can both read version 7.
  2. One saves version 8.
  3. The other must compare its expected version before replacing the cart, then reload or resolve the conflict.
CARD 03What does a connection-server crash require?
  1. Reconnect and authenticate.
  2. Request messages after the last safely applied position.
  3. Recognize repeats.

The network connection ended; saved history, not sticky routing, restores application progress.

Practise this topic in the revision deck ↗

CHECK THE REASONING

Can you explain the choice?

Answer every question, then finish for an immediate score and an explanation for each answer. Aim for 80%, then revisit any gaps.

1 / 10Cart 42 exists only in A’s memory. The next request reaches B. What is missing?
2 / 10A and B both read cart version 7. A commits version 8. What should B’s version 7 conditional replacement do?
3 / 10Which loss is normally recoverable by rebuilding rather than business-data restoration?
4 / 10A chat connection server fails. What is a correct recovery sequence?
5 / 10Why is sticky routing insufficient for durable sessions?
6 / 10When can one stateful game-room owner be useful?
7 / 10A token contains an hour-long permission claim and permission changes now. What must be considered?
8 / 10A purchase commits on A but its reply is lost; the retry reaches B. What protects the effect?
9 / 10What should precede removing a stateful room server?
10 / 10Which description of statelessness is accurate?
0 of 10 answered

CLOSE THE LOOP

Explain it without the page.

Summarise the mechanism, one trade-off, and one failure mode. Then mark this chapter complete.

Go to the source