Sticky Sessions and WebSockets

Keep a user's requests on the same pod when your application runs several replicas, and what to check when WebSocket connections drop.

This page explains how to keep a user's requests on the same pod when your
application runs more than one replica, and what to check first for WebSocket or
real-time connections that drop.

When you need this

By default, the platform ingress (Traefik) spreads requests across all healthy
pods of a Component. That is right for stateless applications. You need sticky
sessions, also called session affinity, when a pod holds per-user state in its
own memory, for example:

  • in-memory login sessions or shopping carts
  • real-time hubs such as SignalR or Socket.IO, where a fallback transport such
    as long polling sends several HTTP requests that must reach the same pod
  • a multi-step flow that stores progress on the pod that started it

Typical symptoms without it: users are logged out at random, or a real-time
client reports an intermittent 404 Not Found or an unknown connection ID. These
symptoms appear only when the Component runs two or more replicas.

Consider a shared session store first

Sticky sessions hide the problem rather than remove it. Before requesting them,
check whether your application can keep its session state outside the pod:

Sticky sessionsShared session store
Pod restart, deployment or scale-inUsers on that pod lose their sessionSessions survive
Load across podsCan become uneven, since long-lived users stay putEven
AutoscalingNew pods only receive new usersNew pods share the load at once
Change neededPlatform configurationApplication configuration

Most frameworks support a Redis-backed session store, and real-time libraries
such as SignalR and Socket.IO offer a Redis backplane or adapter so that any pod
can deliver a message to any connected client. The platform can provide a
managed Redis for this — see Data Services.

ℹ️

Even with sticky sessions, a user moves to another pod whenever their pod is
replaced, which happens on every deployment and during node maintenance. Your
application should tolerate that, for example by reconnecting cleanly.

Requesting cookie-based sticky sessions

The Component configuration in SVIEW does not expose a sticky-session setting,
so stickiness is set up by CTO2B on the ingress. Raise a request in your
dedicated Slack channel and we confirm whether it can be enabled for that
Component. Include:

  • the Environment and the Component name
  • the hostname and path that need stickiness
  • a cookie name, if you need a specific one; otherwise the platform chooses one
  • whether the cookie must be Secure and HttpOnly, and any SameSite
    requirement, for example if the application is embedded in another site

Stickiness works with a cookie that the ingress sets on the first response. The
client must send that cookie back on later requests, which browsers do
automatically. Non-browser clients, such as mobile apps or server-to-server
callers, must store and resend it themselves.

Affinity based on the client IP address, or on the value of an arbitrary request
header, is not offered. Behind a shared load balancer the client IP is not a
reliable key, and Traefik does not balance by header value. If you need routing
by a header, a shared session store is the supported way to achieve it.

WebSocket connections

WebSockets work through the platform ingress with no extra configuration. A
WebSocket stays on the pod it first connected to for its whole lifetime, so a
pure WebSocket connection does not need sticky sessions. You need them only when
the client also uses HTTP requests that must reach the same pod, such as the
negotiate step or a long-polling fallback.

If WebSocket connections close after a period of silence:

  1. Enable the keep-alive or ping option of your WebSocket library, so that the
    connection is never idle for long. An interval of 15 to 30 seconds is a
    common choice.
  2. Make sure the client reconnects automatically. Connections also close when a
    pod is replaced.
  3. If connections still close at a consistent interval, raise a request with
    that interval, the hostname, and the time of a failed connection so it can be
    matched against the ingress logs.

Related articles


Did this page help you?