KamoCRM

Bound upstream calls with a connect and a read timeout

FixAPIService
Shipped
September 23, 2026 at 10:18 AM UTC
Author
Kamo
Commit
eb9cc3b

Both RestTemplate beans were built from a bare JdkClientHttpRequestFactory with no timeout at all. One upstream that accepts the connection and then never answers -- a wedged pod, a deadlock -- parked a gateway thread on that socket forever; enough of those exhaust the finite Tomcat thread pool behind the platform's single /api/** chokepoint and take down every tenant, not just the caller of the slow route. Connect timeout is 5s: the upstream Service always exists in-cluster, so a connect not established by then means the pod behind it is gone. Read timeout is a global 120s rather than a per-prefix value -- this class has no per-route RestTemplate today, the threat (an upstream that never answers) is the same regardless of prefix, and 120s comfortably covers the slowest legitimate calls this gateway forwards (large uploads to /api/docs and /api/media, AI chat, billing exports). Traefik's own inbound respondingTimeouts.readTimeout is 3600s, so nothing ahead of this call was ever going to cut a request shorter than 120s anyway. RestTemplateTimeoutTest drives a real socket that accepts the TCP connection and then never writes a response, using a short timeout in place of the real 120s so the test itself cannot hang the suite, and asserts the client gives up on its own. Reverting to the bare factory makes the underlying call hang past JUnit's own preemptive 3s guard, which is exactly the failure mode this fixes.

All changes

Like what you see shipping?

All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.

Start Free ForeverView Pricing