Skip to content

Add sticky session routing to pin conversations to accounts#2

Merged
Yandrik merged 5 commits into
mainfrom
claude/session-based-routing-13Qpf
May 3, 2026
Merged

Add sticky session routing to pin conversations to accounts#2
Yandrik merged 5 commits into
mainfrom
claude/session-based-routing-13Qpf

Conversation

@Yandrik
Copy link
Copy Markdown
Owner

@Yandrik Yandrik commented May 2, 2026

Summary

Implements sticky session routing to pin each conversation to the same account across multiple turns, preserving the backend's KV cache and reasoning state. Sessions are identified by prompt_cache_key and mapped to accounts in memory with automatic idle-based eviction.

Key Changes

  • New session-store.ts module: In-memory session→account mapping with:

    • getSessionAlias() / setSessionAlias() for session pinning
    • clearSession() / clearSessionsForAlias() for cleanup
    • Automatic pruning of idle sessions (configurable timeout, default 1 hour)
    • Dashboard API helpers: listSessions(), sessionCount(), sessionCountByAlias()
  • Updated rotation.ts:

    • Added sessionId field to AccountSelectionContext interface
    • Early return path in getNextAccount() to reuse pinned account if healthy
    • Fallback behavior when pinned account is unavailable (configurable: 'rotate' or 'fail')
    • Records session→account mapping after selecting a new account
    • Debug logging via OPENCODE_MULTI_AUTH_DEBUG environment variable
  • New settings in types.ts:

    • stickySessionRouting (boolean, default: true)
    • sessionIdleTimeoutMs (number, default: 3,600,000 ms / 1 hour)
    • sessionStickyFallback ('rotate' | 'fail', default: 'rotate')
  • Web console API endpoints in web.ts:

    • GET /api/sessions – list all active sessions
    • DELETE /api/sessions/{sessionId} – clear a specific session
    • DELETE /api/accounts/{alias}/sessions – clear all sessions for an account
    • Dashboard state now includes session counts by alias

Implementation Details

  • Sessions live in memory only; process restart clears them (acceptable since upstream context is also lost)
  • Pruning timer uses unref() to avoid keeping the process alive
  • Health checks are performed before reusing a pinned account; unhealthy accounts trigger fallback logic
  • Session creation timestamp is preserved across updates to track session lifetime

https://claude.ai/code/session_0128Ftvfrm7VHDzxhj29nv1p

claude and others added 5 commits May 2, 2026 13:07
Each conversation is now pinned to the account that handled its first
request, identified by `prompt_cache_key` (forwarded to the backend as
`session_id`/`conversation_id`).  Subsequent turns in the same session
reuse the same account so the backend's KV cache and reasoning state
remain valid.  New sessions are still distributed across accounts using
the configured rotation strategy, so multi-account load-balancing is
preserved at the session level rather than the request level.

New settings in RotationSettings (all with safe defaults):
  stickySessionRouting    – enable/disable (default: true)
  sessionIdleTimeoutMs    – evict after idle (default: 1 h)
  sessionStickyFallback   – 'rotate' | 'fail' when pinned account is
                            unavailable (default: 'rotate')

New file src/session-store.ts: lightweight in-memory map with TTL
pruning, alias-level bulk eviction, and a dashboard-ready list view.

New dashboard API endpoints:
  GET    /api/sessions                    list active session mappings
  DELETE /api/sessions/:id                evict one session
  DELETE /api/accounts/:alias/sessions    evict all sessions for alias
GET /api/state now includes sessions.count and sessions.byAlias.

https://claude.ai/code/session_0128Ftvfrm7VHDzxhj29nv1p
@Yandrik Yandrik merged commit 245de6c into main May 3, 2026
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.

2 participants