Problem
sessions.list RPC takes 5-8s per call in our environment, causing Gateway backpressure under normal polling load.
Root Cause
-
Full row build before filter/limit: listSessionsFromStore() builds the full gateway session row for all 253 sessions before applying limit. Even limit=20 doesn't reduce work.
-
N+1 transcript fallback: buildGatewaySessionRow() calls resolveTranscriptUsageFallback() for ~122/253 sessions that lack totalTokens/contextTokens/estimatedCostUsd fields. Each fallback reads the transcript file from disk.
-
O(N²) child session resolution: resolveChildSessionKeys() scans the full store for every row.
Evidence
- sessions.json deserialization is fast (~15ms total)
- 44% of
sessions.list calls exceed 8s under concurrent polling
- Peak: 234 slow calls at 18:00 when multiple cron jobs trigger
limit parameter has near-zero effect on latency
Suggested Fix
In src/gateway/session-utils.ts - listSessionsFromStore():
- Reorder: filter/sort/limit using cheap entry fields BEFORE
buildGatewaySessionRow()
- Pre-compute child index at list level instead of per-row scan
- Consider TTL cache for repeated calls with no store changes
Environment
- OpenClaw: v2026.3.x
- Sessions: ~253 total across 5 agents
- OS: Darwin/arm64
Problem
sessions.listRPC takes 5-8s per call in our environment, causing Gateway backpressure under normal polling load.Root Cause
Full row build before filter/limit:
listSessionsFromStore()builds the full gateway session row for all 253 sessions before applyinglimit. Evenlimit=20doesn't reduce work.N+1 transcript fallback:
buildGatewaySessionRow()callsresolveTranscriptUsageFallback()for ~122/253 sessions that lacktotalTokens/contextTokens/estimatedCostUsdfields. Each fallback reads the transcript file from disk.O(N²) child session resolution:
resolveChildSessionKeys()scans the full store for every row.Evidence
sessions.listcalls exceed 8s under concurrent pollinglimitparameter has near-zero effect on latencySuggested Fix
In
src/gateway/session-utils.ts-listSessionsFromStore():buildGatewaySessionRow()Environment