Load Balancing
Intermediate 11 min read Load Balancing

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.

sticky sessionsession affinitycookiesource-IP affinityleast-requests
Before we start

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
In 60 seconds

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.

Introduction

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).

Motivation

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.
Think about it

Mental model

Imagine

A barber who remembers how you like your haircut

Think of

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).

Mechanics

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.

First request
LB assigns
Follow-up
State on target
Expiry/drain
Hands-on

Examples

Enable cookie stickiness

Enable cookie stickiness
# ALB: enable stickiness on a target group
aws 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 affinity
aws elbv2 modify-target-group-attributes --target-group-arn <tg> \
--attributes Key=stickiness.enabled,Value=true Key=stickiness.type,Value=source_ip

Cookie stickiness for L7, source-IP for L4 — both pin the client to one backend.

Real world

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.
Guidelines

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.
Watch out

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.
Root cause analysis

Common issues

Error
Office users all land on one target
Root cause

Source-IP affinity with shared egress NAT

Fix

Switch to cookie stickiness (or shared state) so IP sharing doesn't pin a hotspot.

Error
Requests unevenly distributed after enabling stickiness
Root cause

Some clients never expire + target lifecycle

Fix

Shorten durability, use least-outstanding alongside, or drop stickiness for shared state.

When things break

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.
Interviews

Interview checkpoint

Practice

Hands-on lab

Toggle Stickiness and Measure the Distribution Skew
25 min · intermediate
In progress
Objectives
  • 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

0/4 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/1
1

What's the name for routing the same client to the same backend?

Go deeper

Official documentation