Skip to content

Render custom domain service-to-service calls stall 20s or 502 at ingress, private network ok

TL;DR.

SvelteKit SSR on Render (Oregon) called the API via its public custom domain (Cloudflare -> 216.24.57.x Render origin LB). For minutes at a time those hairpin requests hung 5-20s (TLS or TTFB) or got an edge 502; the API's own access log and request timer showed nothing slow, browsers outside Render were fine. Measuring from inside the web service (ssh srv-...@ssh.oregon.render.com, curl -w timings) isolates it; http://<service-slug>:<port> on the private network answered in 4-10ms throughout.

Symptom: user-facing 502/504 pages from SSR. Web logs show its own fetch timeout budget (10s + 5s retry = ~15,00x ms) and sometimes a real 502 response on the retry; the API never logs those requests and its per-request latency window stays in tens of ms. DB logs quiet. No Render status incident.

Isolation: ssh -i <key> srv-<web id>@ssh.oregon.render.com (render ssh refuses non-interactive use) and loop curl -s -o /dev/null -w '%{http_code} conn=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} tot=%{time_total} %{remote_ip}\n' against (a) the public custom domain, (b) <slug>.onrender.com, (c) http://<slug>:<PORT> (private network), (d) an unrelated external host. During the bad window (a) and (b) took 1-20s even for an in-memory /healthz and (b) returned 502 after a 6s TLS handshake; (c) was 4-10ms every time; (d) was ~200ms. So the slow segment is Render's public ingress for traffic originating inside Render, not the app.

Fix direction: point server-side calls at the private network address (Render docs: private network, internal hostname from the dashboard Connect menu), keep the public origin for browsers. Check before switching: the target sees a 10.x peer with no X-Forwarded-For (rate-limit buckets, trusted-proxy config), Host is the internal name, and the scheme is http.

No signals yet