2 months ago
We're seeing intermittent HTTP 500 responses from our Railway-hosted NestJS API (behind Cloudflare). The errors have been increasing in frequency over the past few hours.
Key observations:
- Response body is empty (
content-length: 0) - No
x-railway-request-idheader in the response - No
x-railway-fallbackheader in the response - Only Cloudflare headers are present (
server: cloudflare,cf-cache-status: DYNAMIC) - No corresponding errors in our application logs or server-side Sentry — the request never reaches our NestJS process
- Multiple different endpoints affected (not endpoint-specific)
- The same endpoint can succeed and then fail 200ms later with the same parameters
- Response times are 47–180ms (not a timeout)
- Affects multiple users across different regions in Norway
Evidence from a single user session (cold start at 13:00:58 UTC):
The same endpoint returned 200 (response_body_size: 3088) and then 500 (content-length: 0) within 250ms — same client, same auth token, same parameters.
Sample cf-ray IDs:
2026-03-24 11:46:32 - 9e156f962f48aa04
2026-03-24 13:00:58 - 9e15dca15ad03e6a
All PoP: ARN (Stockholm/Arlanda)
Response headers captured from client (typical example):
alt-svc: h3=":443"; ma=86400
cache-control: private, no-store
cf-cache-status: DYNAMIC
cf-ray: 9e15dca15ad03e6a-ARN
content-length: 0
date: Tue, 24 Mar 2026 13:00:58 GMT
server: cloudflare
server-timing: cfExtPri
No application-level headers (no x-powered-by, no custom headers from our app). No Railway proxy headers at all.
What we've ruled out:
- Not Cloudflare: We checked Cloudflare's Security Analytics and filtered by the Ray IDs above — no firewall events found. No WAF rules, rate limits, or bot challenges were triggered. Cloudflare simply proxied the request to origin (
cf-cache-status: DYNAMIC) and relayed back the 500 it received. - Not our application: No server logs, no server-side Sentry errors for these requests. The same endpoints work fine moments before and after. Our NestJS global exception filter (Sentry) captures all unhandled errors and always returns a JSON body — these 500s have an empty body, confirming they never reached our app.
- Not a timeout (responses come back in 47–180ms)
- Not endpoint-specific (affects GET and POST across many different routes)
Our setup:
- Railway service running NestJS (Node.js)
- Cloudflare DNS proxy in front of Railway
- Traffic pattern: mobile app users, burst of 10-15 concurrent requests on app open
Questions:
- Can you check your edge proxy logs for the cf-ray IDs above to see what happened?
- Is there a known issue with Railway's proxy dropping requests under concurrent load?
- Why is
x-railway-request-idabsent from these error responses?
5 Replies
2 months ago
The absence of x-railway-request-id on those 500 responses confirms they never reached our proxy. Our internal DNS status for api.coachway.io shows the CNAME record as requiring an update (expected target: the Railway-generated hostname for your service), which may explain intermittent failures in the Cloudflare-to-Railway path even though your certificate is valid and domain ownership is verified. You can check the current CNAME target configured in your Cloudflare DNS settings and compare it against the expected value shown in your domain settings on the service's Networking page.
2 months ago
This thread has been marked as private. Any further activity in this thread will only be visible to you and Railway employees.
Status changed to Awaiting User Response Railway • about 2 months ago
Status changed to Awaiting Railway Response Railway • about 2 months ago
2 months ago
Not sure what the bot is talking about, but 500 error codes come from your application. There is nothing on our end that would ever send that status code.
Status changed to Awaiting User Response Railway • about 2 months ago
2 months ago
This thread has been marked as public for community involvement, as it does not contain any sensitive or personal information. Any further activity in this thread will be visible to everyone.
Status changed to Open Railway • about 2 months ago
brody
Not sure what the bot is talking about, but 500 error codes come from your application. There is nothing on our end that would ever send that status code.
2 months ago
Thanks for the quick response.
To clarify...we have fairly extensive evidence that these 500s are not coming from our application:
Empty body: The responses have content-length: 0. Our NestJS framework physically cannot return a 500 with an empty body... its exception filter always writes a JSON payload.
We'd have to go out of our way to produce this.
No application headers: We've now added an x-app: company-api header to every single response our application sends.
The 500 responses don't have it. If our app generated the 500, this header would be present.
No Railway headers: Your own x-railway-request-id header — the one your documentation says is present on proxied responses... is completely absent. So is x-railway-fallback.
If our application handled the request and returned a 500, surely your proxy would still add its own headers to the response on the way back?
No server-side logs: We have Sentry on the server with a global exception filter.
Nothing. No logs, no errors, no trace of these requests ever reaching our process.
Same endpoint, same user, 250ms apart: GET /clients/:id returns 200 with a 3KB body, then 250ms later the exact same request returns 500 with zero bytes.
Our application didn't suddenly forget how to respond to a request it just handled.
Here are cf-ray IDs for your logs: 9e156f962f48aa04 and 9e15dca15ad03e6a. We've also confirmed with Cloudflare that no WAF/security rules triggered — cf-cache-status: DYNAMIC confirms the request was forwarded to origin.
We'd really appreciate it if someone could check the edge proxy logs for these request IDs rather than assuming the 500 must be ours. Happy to get on a call if that's easier.
2 months ago
What is the exact URL where you see these errors, and does this endpoint proxy anything to another Railway-hosted service?
2 months ago
Hello,
We have merged a fix for this; no further action is needed on your end.
