A multi-app-server Acumatica deployment behind a load balancer breaks in a very specific and confusing way if sticky sessions are not configured correctly: users get logged out mid-task, in-progress data entry vanishes, or they see "session expired" errors that have nothing to do with an actual timeout. The cause is almost always a request landing on a different app server than the one holding that user's session state.
Why Acumatica specifically needs session affinity
Acumatica's UI session state — the open screens, the in-progress unsaved edits held in server-side PXCache for that session, the current graph instance — lives in the memory of the specific app server (specific w3wp.exe) that handled the login and subsequent requests. Unlike a fully stateless REST API, an interactive Acumatica UI session is not portable between app servers by default. Send request three of a user's session to app server B when requests one and two went to app server A, and server B has no idea what screen state you are talking about.
Configuring session affinity at the load balancer
The mechanism varies by load balancer, but the principle is the same: bind a client to one backend for the duration of its session, typically via a cookie the load balancer injects, or via source IP hashing (weaker — breaks for users behind a shared corporate NAT egress, where hundreds of users appear to come from one IP and pile onto a single backend).
upstream acumatica_app {
ip_hash; # fallback; prefer cookie-based below when available
server app1.internal:443;
server app2.internal:443;
}
# Preferred: sticky via injected cookie (nginx-plus or sticky module)
upstream acumatica_app_sticky {
sticky cookie srv_id expires=1h domain=.acumatica.example.com path=/;
server app1.internal:443;
server app2.internal:443;
}
For Windows-based load balancing (ARR — Application Request Routing — is still common in front of on-prem Acumatica farms), the equivalent is Client Affinity in the ARR farm configuration, which drops an ARRAffinity cookie tying the client to a specific server.
If the load balancer's affinity cookie expires before Acumatica's own session timeout, a long-idle user (reading a long document, in a meeting with the screen open) can get silently rerouted to a different backend on their next click — and lose in-progress unsaved work with no warning, because the framework has no way to know the physical backend changed underneath the session. Set the affinity cookie's expiry equal to or longer than the site's configured session timeout, not shorter.
Health checks: do not kill sessions to fix a deploy
The other place this bites: a rolling deployment or app pool recycle that takes a backend out of rotation abruptly, rather than draining it, forcibly disconnects every session pinned to that server regardless of stickiness configuration. Configure connection draining (a grace period where the backend stops receiving new sticky assignments but finishes serving existing sessions) before recycling or redeploying to a backend — five to ten minutes is usually enough to let active sessions complete or naturally idle out.
The alternative: do not need affinity at all
Acumatica does support external, shared session state for some deployment topologies (SQL Server-backed or distributed cache-backed session state, depending on version and configuration), which removes the sticky-session requirement entirely and allows genuinely stateless round-robin load balancing. It is more infrastructure to run and is not the default, so most implementations do not bother unless they are specifically chasing zero-downtime rolling deployments — see the blue-green and canary deployment posts in this series for when that trade-off is worth making.
Wrapping up
Sticky sessions are not optional for a standard multi-server Acumatica deployment behind a load balancer — they are a requirement of how UI session state is held in-process. Use cookie-based affinity over IP hashing where the load balancer supports it, match the affinity cookie's lifetime to the session timeout, and drain connections before taking a backend down for deployment rather than yanking it out from under active users.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.