Python · The language, not just syntax

How does asyncio work and where does it fail?

Hardasyncioevent loopcoroutinesUpdated Oct 2026
Quiz this track

Short answer

asyncio runs coroutines cooperatively on an event loop. await yields control while waiting for I/O, letting one thread manage many connections, but any blocking call stalls the entire loop.

A coroutine is declared with async def and only runs when awaited or scheduled as a task. The event loop tracks ready callbacks and I/O readiness, switching between tasks at await points. There is no preemption, so a task that never awaits blocks everything.

python
import asyncio

async def fetch(client, url):
    response = await client.get(url)
    return response.status_code

async def main(client, urls):
    async with asyncio.TaskGroup() as group:
        tasks = [group.create_task(fetch(client, url)) for url in urls]
    return [task.result() for task in tasks]

asyncio.run(main(client, urls))
TaskGroup cancels sibling tasks if one fails, which avoids orphaned work. asyncio.run creates and closes the loop.

Production concerns

  • Never call time.sleep, blocking file I/O or synchronous HTTP inside a coroutine
  • Use asyncio.gather for independent results, TaskGroup for structured failure handling
  • Apply asyncio.timeout or wait_for so a stuck dependency cannot pin a task forever
  • Bound concurrency with a semaphore to avoid exhausting connections or file descriptors

Cancellation is cooperative. A task must reach an await point or check cancellation, and cleanup belongs in finally or an async context manager. Swallowing CancelledError breaks shutdown and timeout logic.

asyncio is concurrency for I/O, not CPU parallelism. CPU-heavy coroutines block the loop; offload them to a process pool or a worker service.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1What happens if a coroutine calls time.sleep?
  2. 2How does cancellation work in asyncio?
  3. 3When would you use gather versus TaskGroup?
  4. 4How do you limit the number of concurrent requests?

Say it in the interview

asyncio runs coroutines cooperatively on an event loop. await yields control while I/O is pending, so one thread can handle many connections. The critical rule is never to block the loop with synchronous calls. I use TaskGroup for structured concurrency, timeouts to bound latency, and semaphores to cap concurrency. Cancellation is cooperative, so cleanup goes in finally blocks.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Python mock interview and get scored feedback on depth, clarity and confidence.