October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk5 min

One Hung API Call Can Stall a 1,000-Run Benchmark: How to Fix It

A hung API request can hold up a concurrent benchmark. Use explicit request and overall time limits, preserve cancellation semantics, and record each run’s outcome separately.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A single API request that never finishes can leave a concurrent Python benchmark waiting indefinitely—or until a client’s unexpectedly long default timeout expires. Set a finite timeout for each request, record timeouts as their own run outcome, and bound the overall benchmark separately if it must finish by a deadline. For independent runs, contain expected failures inside each worker so one failed request does not erase or cancel the rest of the results.

Why one hung API call can stall a benchmark

A benchmark that fans out many requests needs a policy for requests that stop making progress. Without an explicit limit, the run may depend on the HTTP client’s defaults. Those defaults vary: HTTPX documents a timeout after five seconds of network inactivity, while aiohttp’s stable guide documents a 300-second total timeout and a 30-second socket-connect timeout. These are library defaults, not recommended values for every workload; check the documentation for the version actually installed.

As an Amazon Associate I earn from qualifying purchases.

Timeouts also measure different things. A whole-operation deadline limits total elapsed time, while an inactivity timeout can allow a request to continue as long as data keeps arriving. A useful benchmark design distinguishes the request’s total budget from limits on connection setup, sending, receiving, or waiting for a pooled connection.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Set an API call timeout at the right boundary

HTTPX: configure the client or request

HTTPX allows timeout configuration at client level or per request. Its documented default is five seconds of network inactivity, not a five-second cap on the entire operation. If phases need different budgets, configure connect, read, write, and pool timeouts explicitly. See the HTTPX timeout documentation.

aiohttp: choose total and phase limits

aiohttp uses ClientTimeout, configurable for a session or an individual request. Its fields distinguish total duration, connection or pool acquisition, socket connection, and the interval allowed between received data chunks. The stable quickstart documents defaults of 300 seconds total and 30 seconds for socket connection; verify these against the installed version rather than assuming they apply universally. See the aiohttp timeout documentation.

Choose the budget from the workload

There is no evidence-based universal timeout for this benchmark: the API, request type, latency objective, and client are unspecified. Choose a request budget that reflects the service-level expectation and the slow responses the benchmark is meant to measure. A limit that is too short will misclassify legitimate slow responses; one that is too long can make failures dominate the total run time.

Use asyncio timeouts without hiding cancellation

In Python 3.11 and later, asyncio.timeout() provides a timeout context for an awaited operation. asyncio.wait_for() is another option: when its limit expires, it cancels the awaited operation and raises TimeoutError. Neither should be treated as a guaranteed hard wall-clock cutoff. wait_for() waits for cancellation to finish, so the elapsed time can exceed the stated limit while the coroutine performs cleanup.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Cancellation is part of how asyncio implements timeouts. Use try/finally to release local resources, and generally allow CancelledError to propagate after cleanup. Python’s 3.13 task documentation warns: “The asyncio components that enable structured concurrency, like asyncio.TaskGroup and asyncio.timeout(), are implemented using cancellation internally and might misbehave if a coroutine swallows asyncio.CancelledError.” See Python 3.13 asyncio task documentation.

The following conceptual example records each operation’s elapsed time and separates timeout from other errors. Adapt the timeout mechanism and exception boundaries to the Python version and HTTP client in use:

import asyncio
import time

async def one_run(client, request, request_budget_seconds):
    started = time.monotonic()
    try:
        async with asyncio.timeout(request_budget_seconds):
            response = await client.send(request)
            response.raise_for_status()
        return {"status": "ok", "elapsed": time.monotonic() - started}
    except TimeoutError:
        return {"status": "timeout", "elapsed": time.monotonic() - started}
    except asyncio.CancelledError:
        # Let cancellation reach the caller after any needed cleanup.
        raise
    except Exception as exc:
        return {
            "status": "error",
            "error_type": type(exc).__name__,
            "elapsed": time.monotonic() - started,
        }

Do not catch cancellation and convert it into a successful result. If cleanup is required, put it in a finally block and re-raise cancellation afterward.

Keep one failed request from stopping all benchmark runs

The right concurrency behavior depends on whether runs are independent. If the benchmark should report every run, catch and serialize expected request failures within each worker, as in the example above. Then a timeout or HTTP error becomes that run’s outcome rather than an exception that invalidates the whole batch.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

asyncio.TaskGroup and asyncio.gather() have different failure behavior:

  • TaskGroup: if a child task raises an exception, the group cancels its remaining scheduled tasks. This is useful for dependent work or intentional fail-fast behavior, but a benchmark collecting independent results should contain expected per-run failures inside the workers.
  • gather(): by default, an exception from one awaitable is propagated, but the other awaitables are not automatically cancelled and may keep running. Keep task references and deliberately collect results or exceptions so the benchmark can account for all work.

These behaviors are documented in the asyncio task documentation. Pick the policy deliberately: fail fast when later work depends on earlier work; isolate failures when each run is an independent measurement.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Bound the whole benchmark as well as each request

A per-request timeout prevents one operation from waiting without limit, but it does not guarantee that the complete benchmark finishes within a target duration. Bound the overall run separately when the harness has a wall-clock deadline. If that deadline expires, preserve partial results and mark unfinished work as cancelled or incomplete rather than reporting the batch as successful.

Keep the two limits distinct in configuration and reporting: the request budget answers how long one API operation may take, while the benchmark deadline answers how long the full workload may run. An overall deadline can cancel in-flight requests, so cleanup and cancellation handling still matter.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Record outcomes so timeouts do not distort results

Each run should produce a distinguishable outcome, with elapsed time captured using a monotonic clock. At minimum, retain separate categories for:

  • successful responses;
  • HTTP errors;
  • timeouts;
  • cancellations, including work cut short by the overall deadline;
  • other request or client errors.

Keep enough context to interpret results, such as the run identifier, elapsed duration, and error type. A retry or catch-all handler that turns failed requests into apparent successes can make the benchmark misleading. Retry behavior should be specific to the endpoint: do not automatically retry requests that may have caused a side effect unless the API provides an idempotency or deduplication strategy.

A practical decision checklist

  • Identify the HTTP client and inspect the defaults for its installed version.
  • Set explicit request-level limits, covering the phases that matter for the client.
  • Choose whether timeout scope means total operation time, network inactivity, or both.
  • Set a separate overall benchmark deadline if the harness must finish by a fixed time.
  • Choose fail-fast or per-run error containment based on whether tasks are dependent.
  • Record each run’s status and elapsed time; preserve partial results if the batch deadline expires.
  • Allow cancellation to propagate after cleanup instead of disguising it as success.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.