6 days ago
Project ID: 02a2426b-21f8-40ec-b870-3c9689f2c88e
Subject: Edge proxy does not handle Expect: 100-continue — requests hang until client timeout
Hello,
We are hitting an issue where the Railway edge proxy appears to swallow requests that carry the Expect: 100-continue header. The origin never receives them and the client hangs until it times out.
Project: pacific-vision
Service: tienda
Public domain: tienda-production-b534.up.railway.app
Custom domain: api.almadigitalrd.com (CNAME to the above)
Runtime: Node.js 22 (Alpine), Express, listening on $PORT (3000)
== What we measured ==
Same Node.js client, same POST, same multipart body, same endpoint. The only variable is the header and the host.
-
Direct to the container, bypassing the edge:
POST http://127.0.0.1:3000/fe/recepcion/api/ecf with Expect: 100-continue
-> "100 Continue" received in 5 ms, final response in 8 ms
-
Through the Railway domain:
POST https://tienda-production-b534.up.railway.app/fe/recepcion/api/ecf with Expect: 100-continue
-> no "100 Continue", no response, nothing after 8 seconds
-
Through our custom domain:
POST https://api.almadigitalrd.com/fe/recepcion/api/ecf with Expect: 100-continue
-> no "100 Continue", no response, nothing after 10 seconds
-
Same endpoint, same body, WITHOUT the Expect header (plain fetch):
POST https://api.almadigitalrd.com/fe/recepcion/api/ecf
-> HTTP 200 in 190 ms, consistently
Our application access log records case 4 but shows no entry at all for cases 2 and 3, which suggests the request never reaches the container.
Node's built-in HTTP server answers 100-continue automatically, and case 1 confirms it does so correctly here. The behaviour only appears once the request goes through the edge.
== Reproduction ==
Run from any Node.js 22 environment:
const https = require('https');
const b = Buffer.from('--X\r\nContent-Disposition: form-data; name="xml"; filename="p.xml"\r\nContent-Type: text/xml\r\n\r\n\r\n--X--\r\n');
const t = Date.now();
const r = https.request({
host: 'tienda-production-b534.up.railway.app',
path: '/fe/recepcion/api/ecf',
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data; boundary=X',
'Content-Length': b.length,
'Expect': '100-continue'}
}, res => { console.log('response', res.statusCode, Date.now() - t, 'ms'); res.resume(); });
r.on('continue', () => { console.log('100 Continue in', Date.now() - t, 'ms'); r.end(b); });
r.on('error', e => console.log('error', e.message));
setTimeout(() => { console.log('nothing after 8s'); process.exit(0); }, 8000);
Swapping the host for 127.0.0.1:3000 from inside the container succeeds in single-digit milliseconds.
== Why this matters to us ==
This service is a receiver endpoint for the Dominican Republic tax authority (DGII) electronic invoicing programme. During certification, their platform calls our endpoint and expects a signed acknowledgement. Their client is .NET-based, and .NET's HTTP stack sends Expect: 100-continue on POST requests by default. Their platform reported "Error: Http Timeout" against our service and automatically rolled our certification back a step, while our own measurements show the endpoint responding in 190 ms.
We cannot change their client, and this is a government certification process with a compliance deadline.
== What we are asking ==
- Is this a known limitation of the edge proxy?
- Is there a setting, or any supported way, to make the edge answer 100-continue or forward the request regardless?
- If not, can you confirm it so we can put a proxy in front that handles it?
Happy to run any additional test you need, and to give you a window to reproduce against the service directly.
Thank you,
Boiko
Alma Consulting SRL
2 Replies
6 days ago
We've looked into this from our side and haven't found anything on the Railway platform that explains what you're seeing, so working it out means digging into your specific setup.
That's exactly what the Railway community is good at, so we'd like to open your thread as a community bounty. Railway pays a bounty to the community member who solves it, and threads like this usually get picked up quickly.
Opening it makes this entire thread public, including everything already posted. Nothing becomes public until you decide. Use the buttons below.
- Open to the community - Before you click, take a moment to edit or remove anything you'd rather not share. The thread becomes publicly visible right away.
- Keep it private and close the thread - Nothing becomes public and the thread closes.
Status changed to Awaiting User Response Railway • 6 days ago
6 days ago
This thread has been opened as a public bounty so the community can help solve it. The thread and any further activity are now visible to everyone.
Status changed to Open Railway • 6 days ago
6 days ago
Our access log records these requests, but with no status code and no bytes written. The connection reaches the container and dies without a response ever being produced:
12:30:18 POST /fe/recepcion/api/ecf HTTP/1.1 - - "-" "-"
12:33:13 POST /fe/recepcion/api/ecf HTTP/1.1 - - "-" "-"
13:06:31 POST /fe/recepcion/api/ecf HTTP/1.1 - - "-" "-"
13:09:56 POST /fe/recepcion/api/ecf HTTP/1.1 - - "-" "-"
The first three are our own reproduction attempts using Expect: 100-continue. The fourth is the third-party client (the tax authority platform), and it leaves an identical signature.
Every other POST in the same log — hundreds of them — records a status code normally. This pattern appears only on these four.
We also ruled out two things that looked like candidates:
Not the custom domain. The same failure occurs on tienda-production-b534.up.railway.app directly. We reverted the registered URL from our custom domain back to the Railway domain and the third-party client failed identically.
Not TLS. Both hostnames present a 5-link chain, TLSv1.3, handshake in 21–39 ms.
For reference, the same third-party client successfully delivered 9 requests to this same endpoint on 13 August, spaced 4–5 seconds apart, all answered in under 200 ms. The endpoint code has not changed in a way that affects the request path.