A sticky session, also called session affinity or session persistence, is a load balancing behavior that routes every request from one client to the same backend server for the duration of a session. In load balancing, it exists to serve applications that keep user state in server memory, such as a shopping cart or login session.
Stickiness overrides the normal distribution algorithm only for clients that already have a session. New clients are still placed by the configured method, for example round robin or least connections, and are then pinned to the chosen server.
How a sticky session binds a client to a server
A sticky session works by giving the load balancer a key that identifies the client and a mapping from that key to a backend. On the first request, the balancer chooses a server normally and records the choice. On every later request, it reads the key, looks up the mapping and bypasses the balancing algorithm as long as the server is healthy.
The key can live in the client, usually as a cookie, or in a table on the load balancer, keyed by source address or another attribute. The method chosen determines how stickiness behaves behind NAT, across balancer restarts and when servers are added.
| Method | How the key is stored | Strength | Weakness |
|---|---|---|---|
| Balancer-inserted cookie | Cookie set by the load balancer | Precise per browser, no shared table needed | Requires HTTP and visibility into encrypted traffic |
| Application cookie | Existing session cookie such as a session ID | Follows the real application session | Balancer must learn and track the value |
| Source IP affinity | Hash or table of client addresses | Works for any TCP or UDP protocol | Many users behind one NAT land on one server |
| Consistent hashing on a header | Hash of a header or URL parameter | No state on the balancer | Rebalances part of the clients when servers change |
Key parameters of session persistence
Session persistence is controlled by a small set of parameters that decide how long a binding lasts and what happens when the bound server becomes unavailable.
| Parameter | Typical range | Effect |
|---|---|---|
| Affinity timeout | Minutes to hours, often matching the application session | How long an idle binding is kept |
| Cookie lifetime | Session cookie or fixed duration | Whether stickiness survives a browser restart |
| Failover behavior | Rebind or reject | What happens when the bound server fails a health check |
| Draining period | Seconds to tens of minutes | Time existing sessions keep using a server being removed |
| Source mask for IP affinity | /32 to /24 | How coarsely client addresses are grouped |
Connection draining is the parameter most often overlooked. Without it, removing a server for maintenance immediately breaks every session pinned to it, while a draining period lets those sessions finish and stops new bindings to that server.
Sticky sessions compared with stateless designs
Sticky sessions are a workaround for server-side state, and the alternative is to move that state out of the web server. The comparison shows why modern architectures usually prefer stateless servers.
| Approach | Where state lives | Server failure impact | Load distribution |
|---|---|---|---|
| Sticky session | Memory of one server | Users on that server lose their session | Can become uneven |
| Shared session store | Redis, Memcached or a database | Other servers continue the session | Even |
| Client-side token | Signed cookie or token | No session loss | Even |
| Session replication | Copied between servers | Peer holds a copy | Even, with replication overhead |
Even with a shared store, some teams keep weak stickiness for performance, because a server that already holds a client’s cached data answers faster. In that case affinity is an optimization, not a requirement, and losing it causes no errors.
When sticky sessions are the right choice
Sticky sessions are justified when the application cannot be changed to externalize state, or when the state is expensive to rebuild. Typical cases include:
- Legacy web applications that store sessions in local process memory.
- WebSocket and long-polling fallbacks, where several related HTTP requests must reach the same node.
- Stateful protocols such as some VPN or SIP deployments that rely on per-server context.
- Local caches that are expensive to warm, where affinity raises the cache hit rate.
For new applications, the safer default is to make servers stateless and interchangeable, so that autoscaling, rolling deployments and failures do not depend on where a user happened to land.
Pitfalls of sticky sessions
The main risk of stickiness is uneven load. Long sessions accumulate on the servers that were available when traffic began, so newly added servers receive only new users and autoscaling takes effect slowly.
- NAT hot spots: with source IP affinity, an entire corporate office may map to a single backend.
- Session loss on failure: users bound to a failed server are logged out unless state is shared.
- Deployment friction: rolling updates must wait for draining or accept broken sessions.
- Cookie handling: affinity cookies need the Secure and HttpOnly attributes and must not expose internal server names.
Understanding it simply
Imagine a bank with several tellers. Normally each customer goes to whichever teller is free. With a sticky session, once a customer has started a transaction with one teller, that customer always returns to the same teller, because only that teller has the paperwork on the desk.
This keeps things working when the paperwork cannot be shared, but it also means some tellers get busier than others, and if one teller goes home, their customers have to start over.
Applied in practice
An online retailer runs an older shop application on four web servers behind a load balancer. The application keeps the shopping cart in server memory, so without affinity, customers saw their carts empty whenever a request landed on a different server.
The operations team enabled a balancer-inserted cookie with a 30-minute idle timeout and a five-minute draining period for deployments. Cart errors disappeared. During a sale, however, the team noticed that two newly started servers stayed almost idle while the original four ran hot, because existing shoppers stayed pinned. The long-term fix was to move carts into a shared Redis store, after which stickiness became optional and new servers took load immediately.