1. Concurrency vs. Parallelism
To understand asynchronous programming, we must distinguish between concurrency and parallelism:- Parallelism (CPU-Bound): Doing multiple things at the exact same time on multiple CPU cores (e.g., rendering video, matrix multiplication). Python handles this using the
multiprocessingmodule. - Concurrency (I/O-Bound): Having the appearance of doing multiple things at once by context-switching during idle waiting times (e.g., waiting for database queries, disk reads, or API requests). Python handles this using
asyncioandasync/await.
2. Async & Await Declarations
Python’sasyncio framework uses the keywords async def and await to write asynchronous code.
Coroutines
Declaring a function withasync def creates a coroutine. Calling a coroutine does not run it; it returns a coroutine object. To execute it, you must await it.
3. The Event Loop & Task Scheduling
The Event Loop is the engine that runs asynchronous applications. It manages the execution of different tasks:- It runs a task until the task hits an
awaitexpression (blocking I/O). - While that task waits for I/O (e.g., waiting for database results), the loop pauses it and switches to run another ready task.
- Once the I/O operation finishes, the event loop resumes the original task.
Running Tasks Concurrently
To run multiple operations concurrently instead of sequentially, you can group them intoasyncio.create_task() or use asyncio.gather().
4. Why FastAPI Uses Async
FastAPI is built on ASGI (Asynchronous Server Gateway Interface) and supports nativeasync def route handlers.
When a client sends a request to an async def endpoint that performs a database query or external API fetch, FastAPI yields control back to the event loop. The event loop can process other incoming requests in the meantime, resulting in massive throughput gains.