← Docs
Recipe

Python async patterns

Production-ready asyncio patterns for high-concurrency Python services.

Structured concurrency with TaskGroup

Python 3.11 introduced asyncio.TaskGroup, bringing structured concurrency to asyncio. All child tasks are awaited or cancelled together — no orphaned coroutines.

async with asyncio.TaskGroup() as tg:
    tg.create_task(fetch_users())
    tg.create_task(fetch_orders())
# Both complete or both cancelled

Semaphore-bounded fan-out

Cap concurrent I/O with asyncio.Semaphore. Prevents connection pool exhaustion when fanning out to hundreds of endpoints.

sem = asyncio.Semaphore(20)
async def bounded_get(url):
    async with sem:
        return await aiohttp.get(url)

Gather with return_exceptions

asyncio.gather(*tasks, return_exceptions=True) collects exceptions as results instead of short-circuiting. Inspect each outcome after the gather completes.

Timeout with asyncio.timeout

Python 3.11's asyncio.timeout(seconds) context manager raises TimeoutError if the block exceeds the deadline. Prefer it over wait_for for scoped deadlines.

Meridian tip: Combine TaskGroup + Semaphore + timeout for resilient data pipelines. See thefull reference.