Skip to content

WebSocket sticky sessions plus Redis adapter for cross-instance fan-out #2524 - #2549

Merged
jung-thomas merged 7 commits into
DEVfrom
feat/ws-scaling-2524
Sep 30, 2026
Merged

jung-thomas merged 7 commits into
DEVfrom
feat/ws-scaling-2524

Conversation

@jung-thomas

Copy link
Copy Markdown
Contributor

What & why

Fixes #2524 — WebSocket broadcasts are lossy at >1 srv instance. At N>1, tx.emit('tutorialCompleted') on the completing instance only reaches sockets held by that same instance; clients parked on other instances silently miss the event.

The fix is A+B together (either alone is insufficient — see the design doc):

  • (A) Sticky sessions — JSESSIONID affinity cookie on the engine.io handshake, so Gorouter pins each client's multi-request handshake to one instance (fixes handshake flapping).
  • (B) Socket.IO Redis adapter — the plugin-native @socket.io/redis-adapter bridges broadcasts across all instances, so a completion emitted on any instance reaches every subscribed client (fixes the core fan-out loss).

Changes

Area Change
package.json @socket.io/redis-adapter@8.3.0 (exact; 8.x pairs with socket.io 4.x); cds.websocket.adapter block (key: "socket.io"); redis-websocket requires (vcap.label: redis-cache). No "active": true — CF auto-activates via USER=vcap, off-CF stays in-memory so local/tests are untouched.
srv/server.js JSESSIONID cookie on the engine.io handshake via the plugin's ws:ready lifecycle event. Handshake-scoped; does not touch application cookies.
.deploy/mta.yaml tutorials-redis-websocket managed service (redis-cache / standard), bound to both tutorials-srv and tutorials-srv-qa. QA gets a distinct channel key socket.io-qa via env override so it shares one Redis instance without broadcast collision.
docs/comments scaling-playbook row #4 marked resolved; stale "no Redis adapter" comments refreshed; prod.mtaext note updated.

Verification

  • Local npm test — unit suite stays in-memory, adapter dormant, no regression.
  • DEV fan-out (the gate): deploy A+B to DEV with Redis bound, scale tutorials-srv to 2, prove a completion emitted on one instance reaches a WS client on the other, and npm run loadtest:ws at 2 instances stays green. (Running post-merge on fresh origin/DEV.)

Scope boundaries

Out of scope (explicitly not touched): wiring cache-coherence onto Redis (row #5), Redis-backed rate limiters (row #2), emit sites, WS service definitions.

🤖 Generated with Claude Code

@jung-thomas
jung-thomas merged commit 3a3f63e into DEV Sep 30, 2026
7 checks passed
@jung-thomas
jung-thomas deleted the feat/ws-scaling-2524 branch September 30, 2026 10:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant