Learning outcomes
- Understand single-threaded event loop execution
- Prevent event loop blocking in production
Mental model
The AsyncIO event loop is a single-threaded task scheduler running on top of OS I/O multiplexing primitives (epoll on Linux, kqueue on macOS). Coroutines yield control to the loop at await boundaries.
Theory
When a coroutine awaits a non-blocking socket or timer, it registers its file descriptor with system selectors and yields execution back to the loop. The event loop calls select() to block until registered sockets become readable/writable, then wakes up the corresponding task callback.
import asyncio
import time
async def fetch_data(item_id: int) -> dict:
await asyncio.sleep(0.1)
return {"id": item_id, "status": "completed"}
async def main():
start = time.perf_counter()
tasks = [asyncio.create_task(fetch_data(i)) for i in range(100)]
results = await asyncio.gather(*tasks)
print(f"Fetched {len(results)} items in {time.perf_counter() - start:.3f}s")
if __name__ == "__main__":
asyncio.run(main())
Alternatives and trade-offs
AsyncIO outperforms OS thread pools for I/O-bound workloads (10,000+ open sockets). However, CPU-bound operations executed inside a coroutine block the single-threaded loop, stalling all concurrent tasks.
Failure modes and misconceptions
- Blocking the event loop: Calling synchronous blocking functions (
requests.get(),time.sleep(), heavy math) insideasync deffreezes the entire loop. - Unheld Task references:
asyncio.create_task()creates a weak reference; store tasks in a set so GC doesn't drop them mid-flight.
Decision scenario
Use AsyncIO for high-concurrency network services. Offload synchronous blocking I/O or heavy CPU computations to background threads or process pools.
Learning outcomes
- Explain AsyncIO event loop mechanics and epoll socket registration.
- Identify blocking operations that freeze single-threaded event loops.
- Configure task execution pools for high-concurrency web services.
Trade-offs
AsyncIO delivers massive concurrency for non-blocking I/O, but requires non-blocking ecosystem libraries across all database and network paths.
Evidence assessment
Theory and decision mastery
Decision scenario
A developer notices that background tasks scheduled with asyncio.create_task() occasionally stop executing unexpectedly.
What root cause and fix resolve this issue?
Primary sources
- Python 3.12 AsyncIO Event Loop & Asynchronous I/O Specification — Python Software Foundation, verified 2026-07-22