Skip to content

feat(envd): tell reverse proxies not to buffer streaming responses - #3669

Open
eastagiletracker wants to merge 1 commit into
e2b-dev:mainfrom
eastagiletracker:agile-board/envd-stream-no-proxy-buffering
Open

eastagiletracker wants to merge 1 commit into
e2b-dev:mainfrom
eastagiletracker:agile-board/envd-stream-no-proxy-buffering

Conversation

@eastagiletracker

Copy link
Copy Markdown

This PR proposes marking envd's server-streaming responses with X-Accel-Buffering: no so reverse proxies stop holding process output and watch events (Fixes #2707). We include this PR work along with a full history of your repo at https://eastagiletracker.com/projects/751. You can sign in with your GitHub ID to claim ownership of the project.

Process.Start, Process.Connect and Filesystem.WatchDir are server-streaming, but nothing in their responses tells a reverse proxy that. Behind a stock nginx (proxy_buffering on), stream chunks sit in the proxy buffer until it fills, so an interactive PTY looks like it accepts input and prints nothing. On current main (85d0f38), mounting the real filesystem.Handle on a chi mux and opening a WatchDir stream on a temp dir gets a live start event with only Connect-Accept-Encoding, Connect-Content-Encoding, Content-Type and Date in the response headers, and X-Accel-Buffering="".

The change adds a small connect interceptor in packages/envd/internal/services/streaming that sets X-Accel-Buffering: no on responses whose Spec().StreamType includes server streaming. It is wired into the existing connect.WithInterceptors(...) chain in filesystem.Handle and process.Handle. Unary and client-streaming RPCs (ListDir, List, StreamInput, ...) pass through untouched, so they keep whatever buffering or caching the proxy applies today. The header is set before the handler runs, so it is also present when a stream ends in an error. Nothing is removed or renamed, and clients that ignore the header see no difference.

Tests: streaming/interceptor_test.go covers a server stream (with a message and ending in an error), Process.Start, a unary call and a client stream. filesystem/handle_test.go and process/handle_test.go go through the real Handle wiring. With the two service.go edits reverted, go test -run TestHandleDisablesProxyBuffering ./internal/services/filesystem/ ./internal/services/process/ fails with expected: []string{"no"} actual: []string(nil), and it passes with them. go test ./... in packages/envd shows the same set of failures before and after the change. All of those failures are environment-dependent (cgroup, full-disk and network-mount tests on this machine), and none are in the packages touched here. golangci-lint v2.13.2 (from .tool-versions) reports 0 issues on the changed packages.

How this was managed

This work was tracked as https://eastagiletracker.com/projects/751/stories/809774 on https://eastagiletracker.com/projects/751, a board imported from this repo's issues and pull requests (3,652 stories) and used to manage this change.

board

If you'd rather not receive contributions like this, reply no-more-prs on this pull request and we won't open any further ones on your repositories.


Lawrence W. Sinclair
CEO / East Agile
linkedin.com/in/lwsinclair/
eastagile.com

Server-streaming RPCs (Process.Start, Process.Connect,
Filesystem.WatchDir) now respond with X-Accel-Buffering: no, so a proxy
with response buffering on (the nginx default) forwards process output
and watch events as they are written instead of holding them until its
buffer fills. Unary and client-streaming RPCs are unchanged.
@cla-bot

cla-bot Bot commented Sep 29, 2026

Copy link
Copy Markdown

We require contributors to sign our Contributor License Agreement, and we don't have @eastagiletracker on file. You can sign our CLA at https://e2b.dev/docs/cla . Once you've signed, post a comment here that says '@cla-bot check'

This branch has not been deployed

No deployments
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.

envd: streaming RPCs starve behind reverse proxies that buffer responses

1 participant