Meta production automation interview: You need to run 10,000 HTTP health checks from Python in under two minutes. How would you design the asyncio code so it is fast, cancellable, and does not overload dependencies?
Quick Answer
Use asyncio with bounded concurrency, per-request timeouts, structured cancellation, and a result object for every target. In modern Python, TaskGroup helps manage groups of tasks, while semaphores and client timeouts prevent the script from becoming a denial-of-service tool.
Detailed Answer
Think of this like checking 10,000 doors in a city. Sending one inspector door by door is too slow, but sending 10,000 inspectors at once blocks streets and creates a new incident. Good async automation is controlled parallelism: enough concurrency to finish quickly, but not so much that DNS, load balancers, proxies, or the service itself collapse.
Python asyncio is useful for I/O-bound work because the event loop can switch tasks while each request waits on the network. The design should separate three concerns: target generation, bounded execution, and result collection. A semaphore limits the number of in-flight checks. Each request has connect and read timeouts. The caller gets one result per endpoint with status, latency, error class, and retry count.
Modern Python adds structured concurrency through asyncio.TaskGroup. A TaskGroup gives a clear lifetime to a set of related tasks: create them inside the block, wait for completion, and let errors cancel sibling tasks in a controlled way. For health-check automation, many teams choose to catch per-target exceptions inside the worker so one bad endpoint does not cancel the whole scan. For deployment gates, they may do the opposite: fail fast when critical checks break.
At scale, the bottleneck may not be Python. DNS resolvers, NAT gateways, outbound proxies, and service-side rate limits all matter. A mature script includes a configurable concurrency limit, jittered retries for transient network errors, and an allowlist of target domains or clusters. It also emits metrics about timeout rate and p95 latency because the health checker itself becomes part of the deployment system.
The subtle gotcha is cancellation hygiene. If a CI job times out or a deploy is aborted, the script should stop launching new checks and close HTTP connections cleanly. Senior engineers talk about cancellation, finalizers, and bounded resource cleanup, not just await gather.