Edge proxy gzip buffers chunked streaming responses until completion
wasp-sh
PROOP

a month ago

When a client sends Accept-Encoding (as every browser does) and the origin returns a chunked streaming response with a compressible content type, Railway's edge proxy (server: railway-hikari) compresses it with gzip and holds ALL output until the response completes. The client receives the entire stream as a single chunk at the end, which silently breaks incremental delivery (progress streams, AI-style text streaming, long-polling, etc.).

Repro (Express on Node 24, no compression middleware in the app):

  app.get("/stream", async (_req, res) => {
    res.setHeader("Content-Type", "text/html; charset=utf-8");
    res.setHeader("Transfer-Encoding", "chunked");
    res.write("start\n");

    for (let i = 1; i <= 10; i++) {
      res.write(`chunk ${i} `);
      await new Promise((r) => setTimeout(r, 500));
    }

    res.end();
  });

Observed timings reading the body with a fetch reader:

  • Without Accept-Encoding: first chunk at 0.31s, then one chunk every ~500ms. Streaming works.
  • With "Accept-Encoding: gzip, deflate, br, zstd" (what browsers send): response is content-encoding: gzip and the WHOLE body arrives as one chunk at 5.24s, right after res.end(). Streaming broken.

The only difference is the Accept-Encoding request header. The origin sets no compression; the vary: accept-encoding header is added by the edge.

Confirmed escape hatches (both verified on a fresh deployment):

  • Cache-Control: no-transform on the response: edge skips compression, streaming works.
  • Content-Type: text/event-stream: edge skips compression, streaming works (SSE is exempt).

A short report written by Claude after debugging session: https://railway-streaming-report.static.miho.dev/

Closed

2 Replies

Status changed to Awaiting Railway Response Railway 27 days ago


a month ago

Hello,

Thank you for your detailed report and reproduction example.

We have since made a change to our CDN, we no longer compress responses that don't have a content length.

Please let me know if this change has solved your issue.


Status changed to Awaiting User Response Railway 27 days ago


wasp-sh
PROOP

a month ago

Perfect timing. I've re-checked and it indeed doesn't happen anymore.


Status changed to Awaiting Railway Response Railway 26 days ago


Status changed to Solved wasp-sh 26 days ago


Status changed to Closed Railway 26 days ago


Welcome!

Sign in to your Railway account to join the conversation.

Loading...