Streamable proxy drops/fails requests under high concurrent load (fixed 100-buffer channels, no backpressure)
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 2.2k
- Forks
- 300
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 184
Description
Summary
The streamable HTTP→stdio proxy forwards through two fixed-size (buffered=100) channels with non-blocking, drop-on-full sends, drained by single-consumer goroutines. Under high concurrent in-flight load (>~100 simultaneous requests) it degrades ungracefully — hard-failing or dropping — rather than applying backpressure. This is especially relevant to the Modern (2026-07-28) stateless path, which invites high concurrency (no session pinning).
Detail
pkg/transport/proxy/streamable/streamable_proxy.go:
messageCh/responseChare buffered at 100 (hardcoded ~L175-176; noOptionto configure).SendMessageToDestination(~L295) andForwardResponseToClients(~L305):select { case ch <- msg: return nil; default: return err }— non-blocking; on a full channel they fail/drop immediately.dispatchResponsesdrainsresponseChin a single goroutine.
If either consumer is briefly descheduled while >100 requests are in flight:
messageChfull →SendMessageToDestinationerrors →doRequesterrors → HTTP 500.responseChfull → response dropped → the waiting client blocks untilrequestTimeout(60s default) → HTTP 504.
Evidence
Observed while building the Modern no-accumulation resilience test (#5837): a 1000-request concurrent burst intermittently produced a 504, root-caused by an MoE review to this backpressure gap (worse under -race scheduling). The test now throttles its own concurrency to sidestep it, but the production behavior remains.
Suggested direction
Make the buffer sizes configurable and/or apply real backpressure (blocking or context-bounded send) instead of drop-on-full, so burst load degrades in latency rather than dropped/failed requests. At minimum, document the ~100 concurrent-in-flight ceiling.
Context
Enhancement / resilience, surfaced by #5837 Tier-3 testing. Not a regression; pre-existing design limitation.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read pkg/transport/proxy/streamable/streamable_proxy.go, focusing on the messageCh and responseCh setup, SendMessageToDestination, ForwardResponseToClients, and dispatchResponses. Reproduce the burst behavior described from the Modern resilience test in #5837, then verify that concurrent requests no longer fail or time out because either channel is full while preserving request cancellation and timeout behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100