DevOps Peach

System Design for DevOps · Scalability · Lesson 3 of 5

Stateless Services and Session Handling

A stateless service keeps no client data between requests, so any instance can serve any request; sessions move to a shared store such as Redis or into signed tokens, while sticky sessions are a fragile workaround.

Practice interactively →

Horizontal scaling only works if instances are interchangeable. That means no important data lives inside one instance.

flowchart LR
  U["User"] --> LB["Load balancer"]
  LB --> A["api pod 1"]
  LB --> B["api pod 2"]
  A --> R["Redis: sessions"]
  B --> R
  A --> DB["Database"]
  B --> DB
  %% step U: The user sends a session cookie or token with every request.
  %% step LB: The balancer can send each request to any pod.
  %% step A: Pods hold no session in memory; they look it up per request.
  %% step R: Sessions live in a shared, fast store with a time-to-live.
  %% step DB: Durable data lives in the database; nothing important lives in a pod.

What counts as state

State Stateful (bad for scale-out) Stateless alternative
Login session In-memory session map Redis/Memcached, or a signed JWT
Shopping cart Server memory Redis or database
Uploaded files Local disk of the pod Object storage (S3, GCS, Blob)
Scheduled jobs Cron inside every instance One scheduler or a queue
Caches Local cache only Shared cache, or accept short inconsistency

Options for sessions

Option How Trade-off
Sticky sessions LB pins a user to one instance (cookie) Easy, but losing that instance logs users out; uneven load; blocks scale-in
Shared session store Session ID in cookie, data in Redis Extra hop (~1 ms); Redis must be highly available
Client-side token (JWT) Signed token holds user ID and claims No lookup; hard to revoke early, keep it small and short-lived

Why it matters for operations

Stateless pods can be killed, replaced and rescheduled at any time: rolling deploys, autoscaling, spot instances and node maintenance all assume it. In Kubernetes, use a Deployment for stateless services and a StatefulSet only for things that really own data (databases, queues).

The twelve-factor rule

"Processes are stateless and share-nothing; any data that must persist is stored in a backing service." It is the simplest test for a cloud-ready service.

Traps: enabling sticky sessions to hide in-memory state; storing uploads on a pod's disk; JWTs with long lifetimes and no revocation; a single Redis without replication holding every session.

Practice interactively →