Sticky Sessions and Routing
Keeping a customer on the same backend
Sticky sessions (session affinity) pin a client to a backend so its session state survives — but sticky load distribution can under-utilize the fleet. Cookie-based (L7) and source-IP (L4) affinity differ in what they preserve and their failure modes.
What you will learn
- Implement cookie-based and source-IP affinity
- Recognize when stickiness is a workaround for shared state
- Fix hot-request skew caused by sticky routing
Sticky sessions direct a returning client to the same backend within a window (cookie: LB-issued; source-IP: hash). Useful for in-memory sessions — and often a sign you should move session state into a shared store instead.
What is this?
AWS ALB stickiness: duration-based cookie (app-based cookies too), target-group attribute. NLB source-IP affinity: 'stickiness' via target groups. Azure App Gateway: cookie-based affinity; Load Balancer has Session Persistence (source-IP/client-IP+protocol). GCP: session affinity on backend services (generated cookie, header, client-IP). Distributed state (Redis, session DB, sticky-independent) removes the need for affinity entirely — except for calls that need the same node (stateful services).
Why do you need it?
- Legacy apps keep session state in-memory per instance.
- Long-lived workflows need the same node's context mid-transaction.
- Source-IP affinity works where the client doesn't accept cookies.
- Cookie stickiness is transparent and doesn't depend on NAT IP reuse.
Mental model
A barber who remembers how you like your haircut
Sticky session
If you keep your appointment with the same barber (same backend), they remember your style; if the booking system (LB) assigns a random barber each visit (no stickiness), you'd have to re-explain — unless the style (state) lives in the shared book (distributed store).
How it works
- LB sets a cookie (e.g. AWSALB) on the first response; subsequent requests carry it → same target.
- Stickiness has a duration; after expiry the client may be reassigned.
- ALB supports 'app cookie' pinned to your own identifier for longer-lived affinity.
- Source-IP affinity hashes client IP (or IP+port on NLB) to a consistent target until the flow ends.
- During scale-in, drained targets still serve their sticky sessions until drain delay expires.
Sticky path.
Examples
Enable cookie stickiness
# ALB: enable stickiness on a target groupaws elbv2 modify-target-group-attributes --target-group-arn <tg> \ --attributes Key=stickiness.enabled,Value=true \ Key=stickiness.type,Value=lb_cookie \ Key=stickiness.lb_cookie.duration_seconds,Value=3600# NLB source ip affinityaws elbv2 modify-target-group-attributes --target-group-arn <tg> \ --attributes Key=stickiness.enabled,Value=true Key=stickiness.type,Value=source_ipCookie stickiness for L7, source-IP for L4 — both pin the client to one backend.
In production
- A checkout flow holds an in-memory cart on a canary instance with short stickiness window.
- A SIP/VoIP service uses source-IP affinity over NLB for same-call continuity.
- An app migrated out of sticky needs later: Redis moved the session store out of memory.
Best practices
- Prefer shared session state (Redis/session DB) over stickiness for stateless scaling.
- Keep stickiness duration short (minutes) unless a reason demands longer.
- Monitor target distribution when sticky enabled — skew is a silent utilization leak.
- Use drain delay to close sticky sessions gracefully during deploys.
Common mistakes
- Trusting stickiness for a scale-out: canaries stuck to one node underutilize the rest.
- Cookie size/encryption surprises (payload grows) — keep payload minimal.
- Source-IP affinity behind NAT: a whole office rides one IP → one backend hotspot.
- Combining stickiness with weighted canary and wondering why traffic doesn't move.
Common issues
Office users all land on one targetSource-IP affinity with shared egress NAT
Switch to cookie stickiness (or shared state) so IP sharing doesn't pin a hotspot.
Requests unevenly distributed after enabling stickinessSome clients never expire + target lifecycle
Shorten durability, use least-outstanding alongside, or drop stickiness for shared state.
Debugging tips
- Session lost despite cookie: verify cookie name/domain matching across hosts.
- Target skew hot: inspect per-target request metrics under sticky config.
- Legacy app works in dev (single node) but 'loses sessions' in prod — that's the sticky absence, not a bug fix.
- If draining doesn't release a node's sessions, extend drain delay or move state.
Interview checkpoint
Hands-on lab
- Enable cookie vs source-IP stickiness
- Generate a synthetic client trace and measure skew
- Decide when to drop stickiness for shared state
Toggle Stickiness and Measure the Distribution Skew
25 min · intermediate
Quick quiz
What's the name for routing the same client to the same backend?