a month ago
tldr: It seems hikari compresses responses (and therefore drops Content-Length) but railway-edge doesn't?
What we’re seeing
Our service’s responses come back from two different edge proxies at different times — the Server: header moved between railway-hikari and railway-edge — with no deploy or config change on our side. The two behave differently:
- railway-edge (legacy): no response compression. Content-Length preserved, no chunking.
- railway-hikari (new): compresses responses on the fly (gzip/brotli) whenever the request carries Accept-Encoding: gzip/br. Side effects: Content-Length is dropped, response switches to Transfer-Encoding: chunked.
Reproduction (GET any object, direct to the *.up.railway.app domain):
- Accept-Encoding: identity → Content-Length: , no Content-Encoding (both proxies).
- Accept-Encoding: gzip → on railway-hikari: Content-Encoding: gzip, no Content-Length, Transfer-Encoding: chunked. On railway-edge: unchanged, Content-Length still present.
The compression is done by the proxy, not our app (our app returns identical bytes/headers either way — even a small text/plain response gets gzipped through hikari). It also compresses binary/octet-stream payloads, which are already compressed — so it adds cost and breaks Content-Length for no benefit.
Why it’s a problem
We sit behind a CDN (Cloudflare) that always sends Accept-Encoding: br, gzip to the origin, so on hikari every response loses Content-Length. Strict HTTP clients that require Content-Length then fail. The proxy assignment seems to have changed so behavior is intermittent.
Questions:
- Is there a supported way to disable response compression on the new proxy (per service)? Does it honor Cache-Control: no-transform from the origin?
- Why does the proxy assignment change between railway-hikari and railway-edge with no deploy/config change? Is it stable, or auto-migrated?
- Can we pin a service to a specific proxy?
3 Replies
Status changed to Awaiting Railway Response Railway • about 1 month ago
Status changed to Awaiting User Response Railway • about 1 month ago
a month ago
Hey, thanks for the detailed report! We have shipped a fix.
What changed:
Cache-Control: no-transformis now honored - responses that opt out are never gzipped.- Bodies under 256 bytes are no longer compressed (the case where gzip overhead exceeded the savings,)
application/octet-streamand other binary MIMEs are no longer compressed.- Already-encoded responses pass through unchanged.
Large text/HTML/JSON/JS/CSS responses still get gzipped on the wire - that's intentional and what most clients want. If you specifically need byte-preserving passthrough for an endpoint, set Cache-Control: no-transform on it and we'll respect it from now on.
Re your questions:
- Per-service disable knob doesn't exist yet, but Cache-Control: no-transform now works for the same purpose. We'll consider a service-level toggle if there's demand.
- We have been slowly migrating domains to Hikari over the past week; we finished the migration yesterday and now all traffic should pass through Hikari.
- All traffic now passes through Hikari - please let us know if there are any other regressions you see.
If you re-test now you should see Content-Length preserved on the cases that were degrading strict clients.
a month ago
Thanks, fix seems to work.
Status changed to Awaiting Railway Response Railway • about 1 month ago
Status changed to Solved mattijsdp • about 1 month ago
Status changed to Closed Railway • about 1 month ago