Skip to content

fix(http): disable pooling on shared reqwest client (#1092)#1248

Merged
duncanista merged 1 commit into
mainfrom
fix/1092-disable-shared-reqwest-pooling
Jun 10, 2026
Merged

fix(http): disable pooling on shared reqwest client (#1092)#1248
duncanista merged 1 commit into
mainfrom
fix/1092-disable-shared-reqwest-pooling

Conversation

@duncanista

Copy link
Copy Markdown
Contributor

Overview

Fixes the remaining cases of #1092 — customers continuing to see Max retries exceeded, returning request error and TRACES | Request failed: No requests sent after the v94 patch in #1094.

PR #1094 disabled connection pooling on the hyper HttpClient used by the trace flusher and stats flusher. It did not touch the reqwest Client in bottlecap/src/http.rs, which is used by:

  • the trace proxy (proxy_flusher) — the path AppSec and many tracer configurations route through
  • the metrics flusher
  • the logs flusher

That client was still configured with pool_idle_timeout(270s) and tcp_keepalive(120s), leaving idle connections in the pool across Lambda freeze/resume cycles. Connections go stale during a freeze (the OS tears down the remote side while the local kernel still considers them established), and the next request after resume fails with broken pipe / RST → retries exhaust → the user-visible errors.

Change

bottlecap/src/http.rs: replace pool_idle_timeout(270s) + tcp_keepalive(120s) with pool_max_idle_per_host(0). Mirrors the fix in bottlecap/src/traces/http_client.rs and the pattern in libdatadog's new_client_periodic. Each request opens a fresh connection; TLS session resumption inside the client still amortizes the handshake.

Trade-off: one extra TLS handshake per flush. Matches the pre-v93 behavior that customers had no complaints about.

Testing

  • New unit test shared_client_does_not_pool_connections in bottlecap/src/http.rs:
    • Spawns a minimal HTTP/1.1 keep-alive server that counts accepted TCP connections.
    • Issues two sequential GETs through get_client(...).
    • Asserts the server saw 2 connections.
  • Verified the test fails against the unpatched code (opened=1, connection reused from pool) — proves it catches the regression.
  • Verified the test passes against the patched code (opened=2, fresh connection each time).
  • cargo test --lib — 547 tests pass.
  • cargo clippy --lib --tests -- -D warnings — clean.
  • cargo fmt --check — clean.

Other clients (unchanged)

Client File Pooling Notes
hyper HttpClient traces/http_client.rs already disabled (#1094) trace + stats flushers
reqwest Client (shared) bottlecap/src/http.rs disabled here trace proxy, metrics, logs
reqwest Client (Lambda Extensions API) bin/bottlecap/main.rs unchanged localhost-only; pooling irrelevant

The shared reqwest client used by the trace proxy, metrics, and logs
flushers (bottlecap/src/http.rs) was still pooling connections with a
270s idle timeout. PR #1094 / v94 fixed this for the hyper client in
traces/http_client.rs, but the reqwest client — which serves the proxy
path that AppSec and many tracer configurations route through — was
left pooled.

In Lambda, the execution environment can be frozen for seconds to
minutes between invocations. Pooled connections go stale during a
freeze and fail on the next request after resume, surfacing as
"Max retries exceeded, returning request error" followed by
"TRACES | Request failed: No requests sent".

Set pool_max_idle_per_host(0) on the reqwest client builder to match
the pattern already used in traces/http_client.rs and in libdatadog's
new_client_periodic. Each request opens a fresh connection; TLS
session resumption inside the client still amortizes the handshake.

Adds an inline test that spawns a keep-alive HTTP/1.1 server and
counts TCP accepts across two sequential requests. With pooling on,
the count is 1 (reuse); with pooling off, the count is 2 (fresh).
@duncanista
duncanista requested a review from a team as a code owner June 9, 2026 20:09
@duncanista
duncanista requested review from Copilot and shreyamalpani and removed request for Copilot June 9, 2026 20:09
@datadog-prod-us1-4

Copy link
Copy Markdown

Pipelines

Fix all issues with BitsAI

⚠️ Warnings

🚦 1 Pipeline job failed

DataDog/datadog-lambda-extension | e2e-test-status (amd64)   View in Datadog   GitLab

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: e3eda87 | Docs | Datadog PR Page | Give us feedback!

@duncanista
duncanista merged commit d2d30fc into main Jun 10, 2026
59 of 60 checks passed
@duncanista
duncanista deleted the fix/1092-disable-shared-reqwest-pooling branch June 10, 2026 16:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants