Skip to main content

Summary

A common enhancement to minimize latency for http calls is to make use of a keep-alive connection. This prevents a lot of the back and forth chatter between the server and your client and reduces latency on subsequent calls. The further your distance to the server, the more significant the improvement. Keep-alive is a fundamental HTTP optimization, and it matters because of how connections are established. Every new HTTPS connection has to complete a TCP handshake and then a TLS handshake before your request can even be sent — several round trips to the server in total. That setup cost is pure added latency on every call that opens a fresh connection. With keep-alive, your HTTP client keeps the connection open after a response and reuses it for the next request, skipping the connection setup entirely. (Servers still close connections that sit idle too long, but for back-to-back requests you get the reuse for free.)

How to do this

The mechanism is similar across languages and libraries: create one HTTP client (or session) and reuse it for every request, so the underlying TCP/TLS connection is pooled and reused instead of being re-established on every call. Some libraries may require you to explicitly set a keep-alive connection. In most languages/libraries, creating a new client per request defeats keep-alive even if the client’s default settings otherwise support it. Some notes on common defaults:
  • Python requests — doesn’t pool connections unless you create a requests.Session() and reuse the session object across calls.
  • Python httpx — pools connections by default, as long as you reuse the same httpx.Client().
  • OpenAI SDK — built on httpx, so it pools connections by default when you reuse one client instance.
  • Node.js fetch (undici) — pools connections by default; create a custom Agent if you want to tune pool size or keep-alive timeouts.
  • Go net/http — keep-alives are on by default, but only help if you reuse the same http.Client/Transport — a fresh http.Client{} per request still pays the handshake every time.
  • Java — both java.net.http.HttpClient and OkHttp pool connections by default when the same client instance is reused across calls.
When architecting your code, create the client once at startup and share that single instance everywhere — either as a singleton (one global instance the whole app uses) or via dependency injection (the shared client is passed in to the code that needs it). Both patterns guarantee you never accidentally create a new client per request. If you are using LLM agents to set up your code for LLM Gateway, you can use the following instructions:
You can replace the last line’s Python and httpx with your applicable language/library.

Simple examples

Below are concrete, copy-pasteable examples for common languages and libraries. Each one builds a single client and sends two requests through it — subsequent requests reuse pooled connections instead of opening new ones.