An unset timeout is not “no timeout.” It’s the longest timeout in your stack — inherited from whatever library gives up last. So one slow dependency can pin a thread, exhaust the connection pool, and cascade a local hiccup into a system-wide stall. The absence of a decision is still a decision, and usually the worst one.

A good timeout is derived, not guessed: shorter than your caller’s timeout (so you fail before they give up on you), and longer than the p99 of a healthy call (so you don’t kill requests that would have succeeded).

Timeouts must also compose. A chain of five services each patiently waiting 30 seconds means the user waits over two minutes for an answer that stopped being useful after the first ten. Budget the deadline across the whole call chain and pass it down.

Set them deliberately, and pair them with backoff so a timeout doesn’t immediately become a retry storm.