Find the client’s IP address
The edge adds the client’s IP address to two request headers before your origin sees the request:
Use the last entry of
X-Forwarded-For, or X-Envoy-External-Address. Every entry before the last one in X-Forwarded-For came from the client and can be anything.
Headers added to requests
The edge doesn’t add
X-Forwarded-Port.
Where your origin finds the hostname the client used depends on the backend. See The Host header.
Headers passed through unchanged
The edge forwards these headers exactly as the client sent them, so don’t trust them for anything that matters:X-Real-IPTrue-Client-IPForwardedX-Forwarded-Host, onnetworkServicebackendsX-Forwarded-Port
Response headers
The edge passes your origin’s response headers to the client unchanged, including everySet-Cookie header, CORS headers such as Access-Control-Allow-Origin, and caching headers such as Cache-Control. It adds one header:
The edge doesn’t remove headers such as
Server or X-Powered-By, and it doesn’t add security headers such as Strict-Transport-Security. Set or remove those in your origin.
How long a response can stay open
By default, an HTTP response must finish within about 15 seconds of the request reaching the edge. If it doesn’t, the edge ends it:- If your origin hasn’t started answering by then, the client gets a
504 Gateway Timeoutfrom the edge. - If your origin has started answering, the edge cuts the response off at about 15 seconds, even while data is still flowing. This includes streaming responses such as Server-Sent Events (SSE), LLM token streams, and long MCP responses.
Raise the limit
HTTPProxy has no timeout field. Set the limit with a BackendTrafficPolicy, up to 1h, attached to the Gateway that Datum creates for your proxy. The Gateway has the same name as the HTTPProxy.
- macOS / Linux
- Windows (PowerShell)
requestTimeout limits the whole response, from the request arriving to the last byte, so set it longer than your longest stream or download. A larger value is rejected with duration must be less than or equal to 1h0m0s.
A Gateway accepts only one BackendTrafficPolicy. If you’ve already attached one to it, such as for rate limiting, add the timeout block to that policy instead of creating a second one.
If you added the timeout to an existing policy, remove its timeout block and apply the policy again. If you created a dedicated policy with the example above, delete it to restore the default:
- macOS / Linux
- Windows (PowerShell)
WebSockets
The 15-second limit doesn’t end a WebSocket. In testing, an upgraded connection stayed open while messages flowed, and through idle gaps of 2 minutes over 6 minutes in total. No idle limit has been measured.gRPC
In testing, bidirectional gRPC streams of 25 and 45 seconds weren’t cut at 15 seconds. This isn’t a documented guarantee. If your calls can run longer than 15 seconds, raise the limit.Plain HTTP
The load balancer listens on both HTTP (port 80) and HTTPS (port 443). Whether plain HTTP is redirected depends on how the load balancer was set up:datumctl alb createturns on Force HTTPS, which redirects plain HTTP to HTTPS. Turn it off or on withdatumctl alb update NAME --no-force-httpsor--force-https.datumctl compute deploy --http-portcreates a load balancer that serves plain HTTP with no redirect. To add the redirect, rundatumctl alb update NAME --force-https.- An
HTTPProxyyou write yourself serves plain HTTP like any other request, withX-Forwarded-Proto: http. To redirect it, add the rule in HTTP to HTTPS redirect.
Client protocols
Whatever protocol the client uses, the edge makes its own connection to your origin.
How the edge connects to your origin
HTTP or HTTPS
The backend type decides how the edge connects:The Host header
To send a different
Host, see Host header override.
Persistent connections
The edge keeps connections to your origin open and reuses them for later requests. Requests arrive over many connections at once, so don’t rely on one client’s requests sharing an origin connection.gRPC to your origin
gRPC needs HTTP/2 all the way to the origin.endpoint: https://...: works when your origin offers HTTP/2 over TLS, as gRPC servers do.networkService: the port must useh2c. Without it, the edge sends HTTP/1.1, which is incompatible with standard gRPC, and every call fails with502andupstream_reset_before_response_started{protocol_error}.
- With
datumctl compute deploy, add--http2. See Compute and ALB. - On a network service, use
--port=name=grpc,port=9090,app-protocol=h2c. - In a manifest, set
appProtocol: kubernetes.io/h2con the port:
h2c set, every request on that port reaches your instances as HTTP/2, even when the client sent HTTP/1.1. Most servers accept WebSockets only over HTTP/1.1, so serve WebSockets on a different port.