FastAPI has quickly become one of the most popular Python web frameworks for building APIs. With its easy syntax, automatic documentation, and high performance, FastAPI makes API development a breeze.
In this comprehensive guide, we‘ll cover everything you need to know about FastAPI, from the basics to more advanced features. Whether you‘re new to FastAPI or looking to take your skills to the next level, you‘ll find this guide helpful.
What is FastAPI?
FastAPI is a modern, high-performance web framework for building APIs in Python. It builds on top of Starlette and Pydantic to provide an easy-to-use interface for developing RESTful APIs.
Some key features of FastAPI include:
- Fast: Extremely high performance, on par with Node.js and Go
- Fast to code: Increased developer speed thanks to automatic documentation, code completion, and validation.
- Intuitive: Great editor support with autocompletion and inline documentation
- Easy: Designed to be easy to use and learn. Minimizes boilerplate.
- Short : Minimize code duplication – each component packed with functionality
- Robust: Get production-ready code with built-in validation and serialization
- Standards-based: Based on the open standards for APIs: OpenAPI and JSON Schema
So in summary, FastAPI gives you the best of both worlds – the performance and scalability of a lightweight framework combined with the usability and robustness of batteries-included frameworks like Django and Flask.
Why Use FastAPI?
There are many great Python web frameworks, so why use FastAPI over the alternatives? Here are some of the key reasons FastAPI stands out:
Speed and Performance
FastAPI is extremely fast, thanks to its use of Starlette and AsyncIO under the hood. Benchmarks typically show FastAPI outperforming other Python frameworks like Flask and Django by a significant margin.
The asynchronous architecture allows FastAPI to handle more requests using less resources. So you can build highly scalable APIs with minimal servers.
Productivity
FastAPI includes tons of built-in functionality for documentation, validation, serialization, authentication, etc out of the box. This reduces boilerplate code and saves you time as a developer.
The automatic interactive API documentation using OpenAPI is especially useful. It makes testing and understanding your API easy for both internal and external users.
Developer Experience
FastAPI provides superior editor support, including autocompletion and inline documentation popups. This makes development extremely smooth and productive.
The validation checks also help catch bugs early and make debugging easier. Overall, FastAPI offers a fantastic developer experience.
Standards-based
FastAPI is based on OpenAPI standards for defining and documenting APIs. This makes integrating 3rd party tools easy. There are also standards for serialization (JSON Schema), authentication (OAuth 2), and more.
Adhering to standards helps create maintainable and portable APIs that will stand the test of time.
Simple but Flexible
FastAPI hits the sweet spot between simplicity and flexibility. Its simple interface and easy patterns make common tasks straightforward.
But it also provides hooks and customization options to handle more complex scenarios. You can connect to external services, add custom validation, implement different authentication schemes, and more.
How FastAPI Works
Now that we‘ve looked at what FastAPI is and why it‘s useful, let‘s explore how it works under the hood.
ASGI
FastAPI is an ASGI framework, which stands for Asynchronous Server Gateway Interface. ASGI is the spiritual successor to WSGI, which enables asynchronous web apps.
WSGI, used by Flask and Django, handles requests synchronously. Only one request can be handled at a time.
ASGI allows handling requests asynchronously. Multiple requests can be processed concurrently, which improves performance and scalability.
So by building on ASGI, FastAPI gains access to asynchronous capabilities and can handle more requests with fewer resources.
AsyncIO
The magic behind the async capabilities comes from Python‘s built-in AsyncIO module. AsyncIO allows running code concurrently by using cooperative multitasking and an event loop.
Each coroutine (async function) runs until it hits an await statement, where execution is paused and passed back to the event loop. The event loop then resumes any paused coro when their result is ready.
By using AsyncIO, FastAPI can juggle multiple requests concurrently without needing multiple threads. This efficient non-blocking model is why FastAPI has such high performance.
Starlette
FastAPI is built on top of Starlette – a lightweight ASGI framework. Starlette handles the low-level web parts like routing, async request handling, WebSocket support, test client, etc.
Building on Starlette allows FastAPI to get robust web capabilities out of the box without reinventing the wheel. And it can focus on the higher-level API-specific features.
This division of labor is what enables FastAPI to stay simple yet provide advanced functionality.
Pydantic
FastAPI relies heavily on Pydantic for data validation and settings management. Pydantic enforces data types and constraints, giving you automatic validation.
The request body and route parameters get validated against their Pydantic models. Similarly, the response data gets serialized using Pydantic models.
This makes error handling and managing complex data easy. Pydantic powers many of FastAPI‘s great features for productivity and robustness.
Key Features
Now that we‘ve seen how FastAPI works internally, let‘s explore some of the top features it provides:
Declarative Routing
Defining routes is simple and declarative:
from fastapi import FastAPI
app = FastAPI()
@app.get("/users")
def get_users():
return [{"id": 1}]
The path operation decorators like @app.get quickly set up routes. And the function serves as the route handler.
Path parameters are also supported:
@app.get("/users/{user_id}")
def get_user(user_id: int):
return {"id": user_id}
The function parameters become validated path parameters automatically.
Automatic Documentation
FastAPI automatically generates interactive API documentation using OpenAPI:

The docs include path information, parameters, request body, responses, and try-it-out functionality.
Having complete API reference available helps both your team and clients use the API correctly.
Data Validation
Input data and output data gets automatically validated thanks to Pydantic.
For example:
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str
@app.post("/users")
def create_user(user: User):
return user
Here the request body will be validated against the User model. This saves you from writing validation logic manually.
Error Handling
FastAPI provides sane defaults for error handling. It will automatically return pretty JSON responses for validation and other errors:
{
"detail": [
{
"loc": ["body", "name"],
"msg": "field required",
"type": "value_error.missing"
}
]
}
The error details include the location and details of the error.
Dependency Injection
Additional logic like authentication can be abstracted into dependencies:
async def authenticate(token: str):
user = decode_token(token)
return user
@app.get("/protected")
async def protected(user=Depends(authenticate)):
return f"Hello {user}!"
The authenticate function runs before the handler and injects the user into the handler. This allows extracting re-usable middleware.
ORM Integration
FastAPI works great with ORMs like SQLAlchemy thanks to AsyncIO support:
from sqlalchemy.ext.asyncio import create_async_engine
engine = create_async_engine("sqlite+aiosqlite:///db.sqlite3")
@app.get("/users")
async def get_users():
async with engine.connect() as conn:
result = await conn.execute(users_table.select())
users = result.fetchall()
return users
The same techniques apply for other popular ORMs.
Advanced Features
Beyond the basics, FastAPI provides many advanced features:
Background Tasks
Long-running tasks can be run in the background asynchronously using @app.on_event("startup"):
@app.on_event("startup")
async def load_data():
# long startup process
await long_task()
@app.get("/")
async def index():
...
This keeps the main thread responsive while starting up.
WebSocket Support
FastAPI can handle WebSocket connections for real-time communication:
@app.websocket("/ws")
async def websocket(websocket):
await websocket.accept()
# websocket handling logic
The @app.websocket decorator handles the WebSocket connections.
Testing
FastAPI provides test client for easy testing. Just call the app like a function:
from fastapi.testclient import TestClient
client = TestClient(app)
response = client.get("/")
assert response.status_code == 200
The test client handles cookies, headers, etc to mimic a real client.
Deployment
FastAPI can be deployed using any ASGI webserver – Uvicorn, Hypercorn, Daphne, etc.
For example, to run with Uvicorn:
uvicorn main:app --reload
FastAPI also provides integration with various hosting platforms like AWS Lambda, Azure Functions, etc.
Building an API with FastAPI
Let‘s see how to build a real API with FastAPI by creating a simple note taking app.
Project Setup
First, create a new Python project:
mkdir fastapi-notes
cd fastapi-notes
python3 -m venv venv
source venv/bin/activate
pip install fastapi uvicorn
Now create a main.py file with:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_notes():
return [{"title": "FastAPI"}]
And run Uvicorn:
uvicorn main:app --reload
Note Model
Let‘s define a Pydantic Note model:
from pydantic import BaseModel
class Note(BaseModel):
id: int
title: str
This will represent a note object.
Get Notes
We can update our / route handler to fetch notes from a dummy DB:
notes = {
1: {"id": 1, "title": "FastAPI"},
2: {"id": 2, "title": "Learn FastAPI"},
}
@app.get("/")
async def read_notes():
return list(notes.values())
This will return our list of notes.
Add Note
Let‘s add a route to handle adding a new note:
@app.post("/notes")
async def add_note(note: Note):
next_id = len(notes) + 1
note.id = next_id
notes[next_id] = note
return note
It accepts a Note model as the body, assigns an ID, and adds it to the notes dict. The added note gets returned.
Get Single Note
To fetch a single note by ID:
@app.get("/notes/{note_id}")
async def get_note(note_id: int):
if note_id not in notes:
raise HTTPException(status_code=404, detail="Note not found")
return notes[note_id]
This returns 404 if the note doesn‘t exist.
Delete Note
Delete a note by ID:
@app.delete("/notes/{note_id}")
async def delete_note(note_id: int):
if note_id not in notes:
raise HTTPException(404)
del notes[note_id]
return {"message": "Deleted"}
This completes CRUD operations for our notes API!
Testing
To test it, first import TestClient:
from fastapi.testclient import TestClient
Then:
client = TestClient(app)
response = client.get("/")
# test API...
We can send test requests and assert responses.
This gives you an idea of how to build a complete CRUD API with validation, error handling, and testing using FastAPI.
Comparison to Other Frameworks
How does FastAPI compare to other popular Python web frameworks? Let‘s look at some key differences:
FastAPI vs Flask
- FastAPI is faster thanks to ASGI / AsyncIO. Flask uses synchronous WSGI.
- FastAPI has built-in request validation using Pydantic. Flask has no validation.
- FastAPI automatically generates interactive API docs. Flask requires manual docs.
- FastAPI supports advanced features like background tasks and WebSockets.
Overall, FastAPI is better optimized for building APIs vs Flask‘s simplicity.
FastAPI vs Django
- FastAPI is faster and lighter weight compared to Django‘s robustness.
- FastAPI uses ASGI while Django is WSGI based.
- FastAPI has great editor support while Django is less IDE friendly.
- Django provides full featured ORM and admin panel while FastAPI has neither.
FastAPI excels at APIs while Django is suited for full web apps.
FastAPI vs Tornado
- FastAPI offers simpler AsyncIO support than Tornado‘s callbacks.
- FastAPI has built-in validation, docs, dependency injection unlike Tornado.
- FastAPI is better structured for REST APIs and correctness vs Tornado‘s flexibility.
FastAPI improves upon Tornado‘s low-level async support.
So in summary, here is where FastAPI fits in:
- FastAPI vs Flask: Better for APIs and speed rather than simple apps
- FastAPI vs Django: Better for lightweight APIs rather than full featured web apps
- FastAPI vs Tornado: Better structure and features on top of async capabilities
Conclusion
FastAPI is a modern, full-featured framework perfect for building performant REST APIs in Python. Here are some key takeaways:
- FastAPI is fast, easy to use, standards-based, and robust.
- It includes great features like automatic docs, validation, dependency injection, error handling, and more.
- FastAPI is built on Starlette, AsyncIO, and Pydantic to provide its capabilities.
- You can quickly develop scalable and resilient APIs using minimal code.
- FastAPI compares favorably to alternatives for API use cases.
In summary, FastAPI combines the best of both worlds – simplicity and robustness, performance and productivity. APIs that would take thousands of lines in other frameworks can be built with just a few lines in FastAPI.
So if you are looking to build modern REST APIs in Python, definitely give FastAPI a try! It‘s the best framework available for API development today.