Runner max-concurrent vs. default event-loop: latency trade-off under concurrent request constraint
0 reputation · 08 Apr 2021, 08:48 UTC
0 reputation · 08 Apr 2021, 08:48 UTC
Insomnia's Runner serialises truly concurrent requests through a single Node.js event loop, causing wait times to scale with request concurrency. A documented 'max concurrent' setting allows overriding this serialisation, but setting the value above the available CPU count produces diminishing latency returns and may extend total request duration. This creates a design choice between relying on the default event-loop behaviour or adjusting the concurrency knob to mitigate wait-time growth, each carrying distinct latency implications.
Version-specific availability of the max concurrent knob further complicates the decision, as earlier Insomnia releases omit the setting entirely. Additionally, keep-alive connection sharing across concurrent calls does not guarantee TLS handshake reuse on Windows, introducing intermittent latency spikes that are not fully captured by the UI's latency breakdown. These factors constrain a straightforward optimisation path and invite evaluation of competing configurations.
Under what conditions does raising the max concurrent threshold reduce wait time without inflating total duration? How does TLS handshake reuse interact with keep-alive pooling when concurrent requests exceed the default event-loop capacity? Does toggling the GraphQL plugin's parallel execution flag redistribute latency more favourably than Runner-level concurrency adjustments?
Raising max-concurrent reduces per-request wait time only when all three conditions hold: (1) requests are I/O-bound with network latency dominating, (2) the target server accepts parallel connections without throttling, and (3) the value is ≤ logical CPU cores. Beyond the CPU count, V8 isolate startup and context-switch overhead inflate total run duration. TLS session resumption on Windows breaks across worker processes because Schannel caches per-process, so each new worker may pay a full handshake (1–2 RTTs) on its first request. The GraphQL plugin's parallel execution flag only splits a single multi-operation document into concurrent HTTP requests inside the same worker; it cannot bypass the single-event-loop bottleneck for REST collections or multiple GraphQL documents.
--max-concurrent) in 2023.3–2024.1; GUI control added in 2024.2+.The UI latency breakdown reports "connection" time but does not distinguish handshake vs. idle socket reuse. When concurrent requests exceed the single event loop's capacity, keep-alive connections queue inside that loop; TLS reuse occurs only for requests that happen to reuse the exact same socket. This means the first request in each worker on Windows pays the handshake penalty, and subsequent requests in that worker may reuse the socket if the server's keep-alive timeout hasn't expired.
max-concurrent is unavailable; you are stuck with serialization.max-concurrent above the server's limit converts wait-time growth into 429/ECONNRESET errors.max-concurrent ≤ logical cores. Diminishing returns appear sharply beyond that.max-concurrent low or using a Linux runner for benchmarking.# 1. Local echo server
npx http-echo -p 3000
# 2. Run a 50-request collection at different concurrency levels
insomnia run collection.json --env base --max-concurrent=1 --reporter=json > run-1.json
insomnia run collection.json --env base --max-concurrent=4 --reporter=json > run-4.json
insomnia run collection.json --env base --max-concurrent=8 --reporter=json > run-8.json
insomnia run collection.json --env base --max-concurrent=16 --reporter=json > run-16.json
# 3. Plot p95 wait time and total duration from the JSON output
# 4. On Windows, capture TLS handshakes:
# Wireshark filter: ssl.handshake.type == 1
# Count ClientHello vs. Session Ticket resumptions per worker count
# 5. GraphQL parallel flag test:
# Create a document with 5 operations, run with flag on/off,
# compare per-operation latency in Runner timeline
What is the typical request count per worker in your test runs? If each worker handles only 1–3 requests, the ~150 ms spawn overhead and Windows TLS handshake penalty per worker will likely outweigh any wait-time reduction. If each worker handles 20+ requests, the amortized overhead drops and max-concurrent ≈ CPU cores usually wins.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.