Async and concurrency
Top-three Python backend interview topic. Read in order — each file assumes the previous ones.
Foundations
| # | File | Covers |
|---|---|---|
| 01 | The GIL, and free-threaded Python | what the GIL is, why it exists, what it costs |
| 19 | Free-threaded Python | the free-threaded build: how it works, costs, what breaks |
| 02 | Concurrency and parallelism | the distinction, and cooperative vs preemptive |
| 03 | Threads and processes | OS-level: address space, scheduling, cost |
| 04 | Context switching: threads vs coroutines | what a switch actually costs, OS vs coroutine |
Asyncio
| # | File | Covers |
|---|---|---|
| 05 | Coroutines and async def | async def, awaitables, how a coroutine runs |
| 06 | Event loop internals | selectors, yield points, uvloop, Python vs JS loops |
| 07 | asyncio and threads | where the switch happens, and what follows from it |
| 12 | TaskGroup and structured concurrency | TaskGroup vs gather, and picking the right primitive |
| 13 | Cancellation, timeouts and error handling in asyncio | CancelledError, asyncio.timeout, shield, ExceptionGroup |
| 16 | anyio and Trio — structured concurrency | anyio/Trio, and why libraries target them |
| 17 | Async AWS calls: aioboto3 and the alternatives | blocking boto3 on the loop, threads vs aioboto3 |
| 20 | Async Python, end to end | the whole stack in one pass; async generator cleanup, contextvars, eager tasks, asyncio pstree, uvloop |
Choosing a model, and offloading
| # | File | Covers |
|---|---|---|
| 08 | CPU-bound versus I/O-bound | classifying the workload — the decision that drives everything |
| 09 | When to use processes | when processes are the answer |
| 14 | run_in_executor and asyncio.to_thread | asyncio.to_thread, executors, sync drivers in async code |
| 15 | ProcessPoolExecutor: what processes add | process pools, pickling, IPC costs |
| 18 | Blocking and non-blocking I/O | what blocking means, readiness vs completion, files and DNS |
| — | concurrent.futures | the unified pool API, kept with the stdlib notes |
Coordination
| # | File | Covers |
|---|---|---|
| 10 | Synchronization primitives | locks, semaphores, events, conditions — across all three models |
| 11 | Comparing asyncio.Queue and threading.Queue in Python | queues, backpressure, and not mixing the two |
Runnable examples: _examples/.
The 2026 headline
Free-threaded CPython is officially supported as of Python 3.14 (PEP 779) - no longer experimental, though still an opt-in build. Python 3.14 also added stdlib subinterpreters (PEP 734), so “threads, async, or processes?” is now a four-way question. Covered in The GIL, and free-threaded Python.