Welcome to Day 9 of our FastAPI Zero to Hero series!
Today we unlock one of the most powerful (yet misunderstood) tools in modern web development β Async Programming.
π§ What is Async Programming?
Writing non-blocking code can be accomplished through async programming.
This implies that your program doesn't wait for sluggish operations (such as file reads or API requests) to complete before continuing. Alternatively, it can work on other projects in the background when those tasks finish.
π½οΈ Real Life Analogy
You're cooking dinner π³ and waiting for the rice to boil. While it boils, do you just stare at the pot? Nope β you chop veggies or scroll through Instagram reels.
Thatβs asynchronous behavior β youβre multitasking efficiently.
β Why Do We Use Async in FastAPI?
Async is the engine behind that speed and FastAPI is built for speed.
When a route is defined with async def
, FastAPI can:
β
Manage numerous requests concurrently
β
Prevent being held up while waiting on slow tasks
β
Optimise server resources
π Async vs Sync in FastAPI: Real Comparison Example
Async Programming can be your secret weapon when it comes to creating high-performance online APIs. However, how much of a difference is it?
Let's use a real, quantifiable example to compare synchronous and asynchronous code in FastAPI in this blog.
π§ Why This Matters
Web APIs often interact with external services (APIs, databases, etc.). If you do this synchronously, your app will wait idly during these calls β blocking other requests.
But with async, FastAPI can do multiple things at once β like cooking rice and chopping veggies simultaneously ππͺ
π§ͺ The Experiment Setup
Weβll:
β
Call two slow external APIs (simulated with delays)
β
Measure time taken by:
- Synchronous (blocking) code
- Asynchronous (non-blocking) code using
httpx
andasyncio.gather
Letβs roll.
π¦ Install Required Packages
pip3 install httpx request
π The Blocking Version (Sync)
# sync_app.py
from fastapi import FastAPI
import requests
import time
app = FastAPI()
@app.get("/sync-call")
def sync_call():
start = time.time()
r1 = requests.get("https://httpbin.org/delay/2")
r2 = requests.get("https://httpbin.org/delay/2")
end = time.time()
return {
"message": "Done with sync calls",
"time_taken": f"{end - start:.2f} seconds"
}
π What's Taken Place?
- All API calls use
https://httpbin.org/delay/2
to induce a 2-second delay. Due to the synchronous nature of the code, the second request begins only after the first one is finished. As a result, the execution time is ~8 seconds.
This design inhibits the event loop, which results in slower responses and less scalability. β±οΈ Inefficient under large traffic.
β‘ The Async Version (Non-blocking)
# async_app.py
from fastapi import FastAPI
import httpx
import time
import asyncio
app = FastAPI()
@app.get("/async-call")
async def async_call():
start = time.time()
async with httpx.AsyncClient() as client:
r1 = client.get("https://httpbin.org/delay/2")
r2 = client.get("https://httpbin.org/delay/2")
results = await asyncio.gather(r1, r2)
end = time.time()
return {
"message": "Done with async calls",
"time_taken": f"{end - start:.2f} seconds"
}
π What's going on?
The two calls to the API are fired off together.
-
asyncio.gather()
executes them in parallel so that the application can wait for both answers at the same time. Thus, instead of 8!, the total execution time is ~6 seconds.
β‘ Efficient and scalable: Async is perfect for I/O-bound operations like using external APIs since it enables your app to manage several requests at once.
π§ͺ Time to Test
Open two terminals and run both apps:
# Terminal 1: Run the sync server
uvicorn sync_app:app --host 0.0.0.0 --reload --port 9001
Now, test the endpoints by visiting or calling:
http://localhost:9001/sync-call
# Terminal 2: Run the async server
uvicorn async_app:app --host 0.0.0.0 --reload --port 9002
Now, test the endpoints by visiting or calling:
http://localhost:9002/async-call
π§ Key Takeaways
Feature | Sync | Async |
---|---|---|
Code Style |
def , requests
|
async def , httpx
|
Behavior | Blocking | Non-blocking |
Performance | Slower | Faster under load |
Scalability | Limited | High concurrency |
π§° When to Use Async in FastAPI
β Great for:
- Calling external APIs
- Fetching data from databases with async drivers
- File or network I/O
β Not ideal for:
- Heavy CPU tasks (e.g., image processing, number crunching) > Use tools like Celery or background workers for those scenarios.
β Wrap-Up
In this post, we explored the real-world difference between sync and async code in FastAPI by simulating delayed external API calls.
π We discovered:
Synchronous routes reduce down performance by blocking execution.
How asynchronous routes that use async def
and httpx
scale and operate more quickly.
- How
asyncio.gather()
enables I/O-bound tasks to be executed in parallel. Just by altering the way we create and organise our code, async can cut total time roughly in half!
Async programming is a game-changer for creating scalable and responsive online APIs; it's not simply a trendy term.
Whether you're developing real-time dashboards, microservices, or API connections, using async may greatly enhance backend performance and user experience.
π Credits
Huge thanks to the FastAPI Official Documentation by SebastiΓ‘n RamΓrez (@tiangolo) β the best place to learn and explore everything about FastAPI.
π¨βπ» About Me
Hey there! Iβm Utkarsh Rastogi, an AWS Community Builder and passionate cloud-native enthusiast who loves building scalable backend systems and sharing knowledge with the community.
π Connect with me: Utkarsh Rastogi
π¬ Share Your Thoughts β I'd Love Your Feedback!
If you enjoyed today's post or learned something new, I'd truly appreciate it if you leave a comment or share your thoughts π
Your feedback, questions, or even a quick βπ₯ Loved this!β keeps me motivated to continue this journey and share more in the upcoming #FastAPIDaily posts.
β
What did you find most helpful?
β
Anything you'd like explained in the next part?
β
Suggestions for improvement? Iβm all ears! π
Letβs grow and learn together β one FastAPI day at a time π
Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.