Hubbry Logo
search
logo
FastAPI
FastAPI
current hub

FastAPI

logo
Community Hub0 Subscribers
Read side by side
from Wikipedia
FastAPI
DeveloperSebastián Ramírez
Initial releaseDecember 5, 2018; 6 years ago (2018-12-05)[1]
Stable release
0.120.1[2] Edit this on Wikidata / 27 October 2025; 2 days ago (27 October 2025)
Repositorygithub.com/tiangolo/fastapi
Written inPython
TypeWeb framework
LicenseMIT
Websitefastapi.tiangolo.com

FastAPI is a high-performance web framework for building HTTP-based service APIs in Python 3.8+.[3] It uses Pydantic and type hints to validate, serialize and deserialize data. FastAPI also automatically generates OpenAPI documentation for APIs built with it.[4] It was first released in 2018.

Components

[edit]

Pydantic

[edit]

Pydantic is a data validation library for Python. While writing code in an IDE, Pydantic provides type hints based on annotations.[5] FastAPI extensively utilizes Pydantic models for data validation, serialization, and automatic API documentation. These models are using standard Python type hints, providing a declarative way to specify the structure and types of data for incoming requests (e.g., HTTP bodies) and outgoing responses.[6]

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float
    is_offer: bool | None = None


@app.post("/items/")
def create_item(item: Item):
    # The 'item' object is already validated and typed
    return {"message": "Item received", "item_name": item.name}

Starlette

[edit]

Starlette is a lightweight ASGI framework/toolkit, to support async functionality in Python.[7]

Uvicorn

[edit]

Uvicorn is a minimal low-level server/application web server for async frameworks, following the ASGI specification. Technically, it implements a multi-process model with one main process, which is responsible for managing a pool of worker processes and distributing incoming HTTP requests to them. The number of worker processes is pre-configured, but can also be adjusted up or down at runtime.[8]

OpenAPI integration

[edit]

FastAPI automatically generates OpenAPI documentation for APIs. This documentation includes both Swagger UI and ReDoc, which provide interactive API documentation that you can use to explore and test your endpoints in real time. This is particularly useful for developing, testing, and sharing APIs with other developers or users. Swagger UI is accessible by default at /docs and ReDoc at /redoc route.[9]

Features

[edit]

Asynchronous operations

[edit]

FastAPI's architecture inherently supports asynchronous programming. This design allows the single-threaded event loop to handle a large number of concurrent requests efficiently, particularly when dealing with I/O-bound operations like database queries or external API calls. For reference, see async/await pattern.

Dependency injection

[edit]

FastAPI incorporates a Dependency Injection (DI) system to manage and provide services to HTTP endpoints. This mechanism allows developers to declare components such as database sessions or authentication logic as function parameters. FastAPI automatically resolves these dependencies for each request, injecting the necessary instances.[10]

from fastapi import Depends, HTTPException, status
from db import DbSession


# --- Dependency for Database Session ---
def get_db():
    db = DbSession()
    try:
        yield db
    finally:
        db.close()


@app.post("/items/", status_code=status.HTTP_201_CREATED)
def create_item(name: str, description: str, db: DbSession = Depends(get_db)):
    new_item = Item(name=name, description=description)
    db.add(new_item)
    db.commit()
    db.refresh(new_item)
    return {"message": "Item created successfully!", "item": new_item}


@app.get("/items/{item_id}")
def read_item(item_id: int, db: DbSession = Depends(get_db)):
    item = db.query(Item).filter(Item.id == item_id).first()
    if item is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Item not found")
    return item

WebSockets support

[edit]

WebSockets allow full-duplex communication between a client and the server. This capability is fundamental for applications requiring continuous data exchange, such as instant messaging platforms, live data dashboards, or multiplayer online games. FastAPI leverages the underlying Starlette implementation, allowing for efficient management of connections and message handling.[11]

# You must have 'websockets' package installed
from fastapi import WebSocket


@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        await websocket.send_text(f"Message text was: {data}")

Background tasks

[edit]

FastAPI enables the execution of background tasks after an HTTP response has been sent to the client. This allows the API to immediately respond to user requests while simultaneously processing non-critical or time-consuming operations in the background. Typical applications include sending email notifications, updating caches, or performing data post-processing.[12]

import time
import shutil
from fastapi import BackgroundTasks, UploadFile, File
from utils import generate_thumbnail


@app.post("/upload-image/")
async def upload_image(
    image: UploadFile = File(...),
    background_tasks: BackgroundTasks
):
    file_location = f"uploaded_images/{image.filename}"
    # Save uploaded image
    with open(image_path, "wb") as f:
        contents = await file.read()
        f.write(contents)

    # Add thumbnail generation as a background task
    tasks.add_task(generate_thumbnail, file_location, "200x200")

    return {"message": f"Image '{image.filename}' uploaded. Thumbnail generation started in background."}

Example

[edit]

The following code shows a simple web application that displays "Hello, World!" when visited:

# Import FastAPI class from the fastapi package
from fastapi import FastAPI

# Create an instance of the FastAPI app
app = FastAPI()

# Define a GET route for the root URL ("/")
@app.get("/")
async def read_root() -> str:
    # Return a plain text response
    return "Hello, World!"

See also

[edit]
[edit]

References

[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
FastAPI is a modern, high-performance web framework for building APIs with Python 3.7 and above (with Python 3.10+ recommended, ideally 3.12+ for best compatibility, features, and performance), utilizing standard Python type hints to enable automatic data validation, serialization, and interactive documentation.[1] It is designed to speed up development by 200–300% while reducing the number of bugs by about 40%, thanks to its intuitive interface and strong editor support.[1] Developed by Sebastián Ramírez and first released in late 2018, FastAPI has rapidly gained popularity as one of the most loved Python frameworks for its simplicity and efficiency in creating production-ready APIs.[2][3] To effectively learn and use FastAPI in 2025 or 2026, intermediate Python knowledge is required. Essential concepts include core Python syntax, data types, control flow, lists/dicts/sets, comprehensions, functions (including args/kwargs), modules/packages, object-oriented programming (classes, inheritance, methods, attributes), type hints/annotations (critical for parameter definition, validation, and auto-docs), asynchronous programming (async def, await syntax, highly recommended for performance), and decorators (used for defining routes). Knowledge of generators, context managers, and basic web concepts (HTTP methods, JSON, REST) is also helpful. Users should master these before starting the official FastAPI tutorial.[1] FastAPI builds on established libraries such as Starlette for asynchronous web handling and Pydantic for data parsing and validation, ensuring compatibility with ASGI servers like Uvicorn.[1] Its performance is comparable to frameworks in Node.js and Go in many scenarios (e.g., plaintext responses), although Node.js frameworks like Fastify may outperform in certain database-intensive tests according to TechEmpower Round 23 (2025) benchmarks, while FastAPI remains highly competitive among Python web frameworks and offers unique productivity advantages.[4][3] Key standards like OpenAPI (for API documentation) and JSON Schema (for model definitions) are fully integrated, allowing automatic generation of interactive Swagger UI and ReDoc interfaces at runtime.[1] The framework emphasizes developer productivity through type-driven development, which provides immediate feedback via IDE autocompletion and error detection during coding, rather than at runtime.[1] It supports modern Python features like async/await for concurrent operations and is production-ready, with widespread adoption by companies for scalable microservices through synchronous HTTP calls and asynchronous event-driven mechanisms, as well as data-driven applications.[1] FastAPI's design philosophy prioritizes standards compliance and minimal overhead, making it suitable for both small prototypes and large-scale deployments.[5]

Introduction

Overview

FastAPI is a modern web framework designed for building APIs with Python 3.7 and later versions, utilizing standard Python type hints to facilitate development.[1] It prioritizes high performance—comparable to frameworks in Node.js and Go—while offering ease of use through minimal boilerplate code and automatic generation of interactive API documentation.[6] Among its key benefits, FastAPI reduces development time by minimizing bugs via built-in type checking and data validation, and it ensures compatibility with OpenAPI and JSON Schema standards for seamless integration and documentation.[7][6] Created by developer Sebastián Ramírez, FastAPI was initially released in December 2018. As of March 1, 2026, FastAPI version 0.131 is not the current version; the latest version is 0.134.0, released on February 27, 2026, with continued updates enhancing support for Python 3.12 and beyond.[8]

Prerequisites for Learning FastAPI

To learn FastAPI effectively in 2025 or 2026, intermediate knowledge of Python is recommended. The framework leverages advanced Python features, particularly type hints, and assumes familiarity with the following core concepts:
  • Core Python syntax and features, including data types, control flow, collections (lists, dictionaries, sets), comprehensions, functions (with positional and keyword arguments), and modules/packages.
  • Object-oriented programming, encompassing classes, inheritance, methods, and attributes.
  • Type hints and annotations, which are essential to FastAPI's design for parameter declarations, data validation, and automatic documentation generation (using the typing module, including constructs such as Union and Optional).
  • Asynchronous programming with async def and await syntax, highly recommended for performance in I/O-bound applications, although synchronous code remains supported.
  • Decorators, which are used to define API routes and endpoints.
Additional helpful concepts include generators and context managers. FastAPI assumes basic familiarity with web development concepts such as HTTP methods, JSON, and REST principles, but its primary innovation lies in leveraging Python type hints. Developers are recommended to use Python 3.10 or higher, ideally Python 3.12 or higher, for optimal compatibility and access to modern language features. After acquiring these prerequisites, users should begin with the official FastAPI tutorial.[1][7][9] For Python developers, the fastest way to learn FastAPI and Docker is a hands-on, project-based approach using the official documentation. First, follow the official FastAPI User Guide tutorial (https://fastapi.tiangolo.com/tutorial/) to build a basic API application. This interactive, code-focused tutorial covers essential topics such as endpoints, data validation, and asynchronous support and is typically completable in 2-4 hours. Next, Dockerize the resulting application using the official FastAPI Docker guide (https://fastapi.tiangolo.com/deployment/docker/), which involves creating a simple Dockerfile, building the image, and running the container—usually achievable in 1-2 hours while benefiting from Docker layer caching for efficient iterations. This build-then-containerize method promotes rapid mastery through practical application. Alternatively, those preferring video instruction can begin with a 1-3 hour FastAPI crash course on YouTube for an overview before applying the concepts through the official documentation. This structured path complements the prerequisite knowledge by providing immediate practical application after mastering the required Python concepts.[10][11]

Development History

FastAPI was created by Sebastián Ramírez, known online as tiangolo, a software developer originally from Colombia who resides in Berlin, Germany.[12] Ramírez drew inspiration from established frameworks such as Flask for its simplicity and ease of use, Django for its comprehensive features in a more lightweight form, and Node.js's Express for its high performance and rapid development capabilities.[13] His goal was to combine these strengths with Python's emerging type hinting features to build a modern API framework that prioritized speed, developer productivity, and automatic documentation generation.[1] The framework was first released on December 7, 2018, as an open-source project under the MIT license, with its initial version (0.1.0) hosted on GitHub. From the outset, FastAPI integrated Pydantic for data validation and serialization, leveraging the library's recent availability to enable type-based model definitions. It was built on top of the Starlette ASGI framework, which provided the asynchronous foundation necessary for high-performance web applications. Key milestones in FastAPI's evolution include the adoption and deepening integration of Starlette's capabilities in early 2019 updates, enhancing its support for asynchronous operations. On July 7, 2023, version 0.100.0 was released, marking the 100th minor version and introducing full compatibility with Pydantic v2, along with improved OpenAPI schema generation. By 2025 and into 2026, ongoing releases such as 0.121.0 in November 2025 continued to refine asynchronous support, including better handling of lifespan events and dependency scopes, while facilitating integrations for machine learning workflows through enhanced Pydantic model flexibility, with the latest version being 0.134.0 released on February 27, 2026, as of March 1, 2026.[14] FastAPI's growth has been rapid, amassing over 84,000 GitHub stars by mid-2025, approximately 91,700 as of November 2025, and approximately 94,800 as of February 2026, reflecting widespread adoption among developers and organizations.[15][2] Major companies, including Uber for real-time data processing APIs, Microsoft for internal tools, and Netflix for production services, have integrated FastAPI into their stacks due to its performance and ease of maintenance.[1] The project's success stems from robust community contributions, with hundreds of pull requests merged annually on GitHub, fostering iterative improvements. A pivotal aspect of FastAPI's design is its async-first architecture, which capitalized on enhancements to Python's asyncio module introduced in version 3.5 (2015) and matured in subsequent releases like 3.6 with native async/await syntax. This shift enabled FastAPI to handle concurrent I/O-bound tasks efficiently from inception, setting it apart from synchronous predecessors and aligning with modern web demands.[9]

Technical Foundations

Pydantic Integration

Pydantic is a data validation library for Python that leverages type annotations to define and validate data models, ensuring runtime type checking and parsing of untrusted input data such as JSON from API requests.[16] It supports built-in types like integers, strings, and dates, as well as custom constraints, converting data to the specified types or raising a ValidationError if invalid.[17] FastAPI integrates Pydantic deeply for handling request and response data, using Pydantic models to automatically validate incoming JSON payloads against declared schemas, serialize validated data into Python objects, and generate error responses with detailed validation messages for clients.[18] This integration enables direct use of Pydantic models in path operation functions, where request bodies are parsed and validated before execution, and responses are filtered and serialized to match the model.[6] Best practices for using Pydantic response models in FastAPI include defining separate Pydantic models for input (requests) and output (responses) to avoid exposing sensitive data (e.g., include password in UserIn but exclude it in UserOut). Model inheritance from a shared base model is recommended to reduce code duplication while maintaining consistency across related schemas. The response_model parameter should be specified in path operation decorators (e.g., @app.get(..., response_model=UserOut)) to enforce validation, data filtering, serialization, and accurate OpenAPI documentation. Proper model design is preferred over manual field exclusion for better maintainability and JSON Schema accuracy in documentation. Parameters like response_model_exclude_unset=True to omit unset or default fields and response_model_exclude_none=True to exclude None values can reduce response size, especially useful for models with many optional fields. When returning dicts or ORM objects, using response_model ensures filtering and validation even if the function return type differs.[19] Key concepts in this integration include the BaseModel class, which serves as the foundation for defining data schemas through class attributes with type hints.[17] Validators allow custom logic, such as field-level checks with @field_validator for post-parsing constraints (e.g., ensuring a value meets business rules) or model-level validation with @model_validator for cross-field dependencies.[20] Custom types extend validation, like EmailStr for email format enforcement requiring the email-validator package, while strict mode—enabled via model configuration—disables type coercion to enforce exact type matching and prevent implicit conversions.[21] Serialization is handled through methods like model_dump() to produce JSON-compatible output from validated instances.[17] The benefits of this integration include early error detection during development and runtime, reducing bugs from invalid data, and automatic generation of OpenAPI schemas from Pydantic models for interactive documentation.[6] It also provides IDE support through type hints, improving code readability and maintainability without introducing new syntax.[22] For example, a User model can be defined as follows:
from datetime import date
from pydantic import BaseModel, EmailStr

class User(BaseModel):
    id: int
    name: str
    email: EmailStr
    joined: date
This model validates inputs like User(id=1, name="Alice", email="[email protected]", joined="2023-01-01"), ensuring the email is properly formatted and coercing the date string if needed, while generating corresponding OpenAPI schema documentation.[17][23][18] To demonstrate response model best practices, consider defining separate models with inheritance:
from pydantic import BaseModel, EmailStr
from datetime import date

class UserBase(BaseModel):
    name: str
    email: EmailStr
    joined: date

class UserIn(UserBase):
    password: str

class UserOut(UserBase):
    id: int
In a path operation, specify the response model to filter out sensitive fields:
@app.post("/users/", response_model=UserOut)
async def create_user(user: UserIn):
    # Process creation (e.g., hash password, save to database)
    # Return with added id
    return {"id": 1, "name": user.name, "email": user.email, "joined": user.joined}
This ensures the password is not exposed in responses, reduces duplication via inheritance, and produces accurate OpenAPI documentation.[19]

Starlette ASGI Framework

Starlette serves as the foundational ASGI framework for FastAPI, providing the core web handling capabilities that enable asynchronous Python web applications.[6] The Asynchronous Server Gateway Interface (ASGI) is a standard specification designed to facilitate communication between asynchronous-capable web servers and Python web frameworks or applications, acting as a successor to the synchronous Web Server Gateway Interface (WSGI).[24] Unlike WSGI, which processes requests sequentially in a blocking manner, ASGI supports non-blocking, concurrent operations through asynchronous functions and coroutines, allowing for efficient handling of multiple simultaneous connections, such as in real-time applications.[25] This enables true asynchrony in Python web services, leveraging libraries like asyncio for improved performance in I/O-bound tasks.[26] Starlette, a lightweight and production-ready ASGI toolkit, powers FastAPI by offering essential components for building high-performance async web services, including robust routing mechanisms that map HTTP methods and paths to handler functions or coroutines.[27] In FastAPI, these routing features are extended through intuitive decorators such as @app.get(), @app.post(), and others, which simplify the definition of path operations while internally utilizing Starlette's Route and Router classes to match incoming requests and dispatch them appropriately.[6] Starlette also provides comprehensive middleware support, allowing developers to intercept and modify requests and responses globally—for instance, via built-in options like CORSMiddleware for handling cross-origin resource sharing (CORS) and session management. Additionally, it includes flexible request and response objects, such as the Request class for accessing headers, query parameters, and body data, and various response types like JSONResponse for structured outputs. Key to Starlette's integration in FastAPI are its support for startup and shutdown events, which allow applications to execute code during initialization (e.g., database connections) or cleanup (e.g., resource release), managed through lifespan handlers that align with ASGI's protocol. WebSocket functionality is natively provided by Starlette, enabling bidirectional, full-duplex communication channels for real-time features, with FastAPI exposing this through @app.websocket() decorators that build on Starlette's WebSocket and WebSocketDisconnect classes. Exception handling is another core component, where Starlette's add_exception_handler method allows custom responses for errors, ensuring graceful degradation in async contexts. Overall, these elements make Starlette the versatile backbone for FastAPI's web layer, with applications typically run using compatible ASGI servers like Uvicorn for deployment.[6]

Uvicorn ASGI Server

Uvicorn is a high-performance ASGI server implementation for Python, designed to support HTTP/1.1 and WebSockets while providing a minimal interface for asynchronous web frameworks. It achieves its speed through optional integrations with uvloop, a fast event loop based on libuv, and httptools, an efficient HTTP parser written in Cython. As the default server for FastAPI applications, Uvicorn enables seamless execution of API endpoints in both development and production environments.[28] Installation of Uvicorn is straightforward via pip: pip install uvicorn. For basic usage in development, it is invoked from the command line as uvicorn main:app --reload, where main refers to the Python module containing the FastAPI instance app, and --reload enables automatic restarting on code changes. This command binds to 127.0.0.1:8000 by default, but can be customized with options such as --host [0.0.0.0](/page/0.0.0.0) to listen on all interfaces or --port 8080 to specify a different port. SSL support is available through --ssl-keyfile and --ssl-certfile flags for secure connections. For multi-worker configurations, Uvicorn supports the --workers option to spawn multiple processes, with a default of 1; this can be combined with environment variables like WEB_CONCURRENCY for dynamic scaling. In production, it integrates well with Gunicorn as a process manager by using Uvicorn workers: gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker, which requires the uvicorn[standard] package for full compatibility.[29] Production deployments emphasize reliability over development conveniences. Auto-reload must be disabled by omitting --reload, as it is incompatible with multi-worker mode and unsuitable for live environments.[29] Logging is configurable via --log-level (e.g., info or error) or --log-config for structured formats in JSON, YAML, or INI, with access logs toggled using --access-log. A common issue in development is that unhandled exceptions result in a "500 Internal Server Error" response with only a basic access log entry (e.g., "INFO: 127.0.0.1:port - "GET /path HTTP/1.1" 500 Internal Server Error") and no detailed traceback or exception information in the console. This is often caused by Uvicorn's default logging configuration setting disable_existing_loggers: True, which disables loggers from FastAPI and Starlette (including ServerErrorMiddleware responsible for traceback logging).[30] To ensure detailed error information is available:
  • For development, initialize FastAPI with debug=True: app = FastAPI(debug=True). This includes full tracebacks in the JSON error response body.[31]
  • Customize Uvicorn logging by providing a log configuration (dictionary or file) that sets "disable_existing_loggers": False or explicitly enables relevant loggers (e.g., "uvicorn.error", "starlette.exception"), then pass it via uvicorn.run(app, log_config=config) or --log-config.
  • Run Uvicorn with --log-level debug to increase verbosity and capture detailed error logs.
  • As an alternative or complement, add custom middleware or exception handlers to manually log exceptions using logging.exception() or traceback.format_exc().
Applications are commonly deployed in Docker containers, such as those built from official images like tiangolo/uvicorn-gunicorn-fastapi, or on cloud platforms with reverse proxies like Nginx for load balancing and security.[11][32] Regarding performance, Uvicorn demonstrates exceptional throughput, handling 1,014,344 requests per second in plaintext benchmarks from TechEmpower Round 23 (as of November 2025), positioning it comparably to Node.js frameworks like Fastify at 1,175,038 requests per second.[33] This efficiency stems from its asynchronous design and optimized dependencies, making it suitable for high-traffic APIs.

Core Features

Type Hints and Automatic Validation

FastAPI leverages Python type hints, introduced in Python 3.5 and available via the typing module since Python 3.6, to enable automatic data validation directly within path operation function signatures. These annotations, such as str, int, List[int] from typing import List, or Optional[str] from typing import Optional, declare expected types for parameters like path variables, query parameters, and request bodies, allowing the framework to infer and enforce data structures without additional code.[7] The automatic validation process occurs before the function executes: FastAPI parses incoming data—such as path parameters (e.g., /items/{item_id} with item_id: int), query parameters (e.g., ?q: [str](/page/€STR)), or JSON bodies—and converts it to the hinted types while checking for compliance. If mismatches occur, such as providing a string where an integer is expected, validation fails, preventing invalid data from reaching the application logic. For request bodies, FastAPI employs Pydantic models defined with type hints (e.g., a class inheriting from BaseModel with fields like name: [str](/page/€STR) and price: float) to handle complex structures, including nested models where one Pydantic class embeds another, and union types like str | None for optional or alternative values. Best practices recommend defining separate Pydantic models for input (requests) and output (responses) to enhance security and maintainability.[18][7][34] Response models extend this capability to outputs by specifying return types in function signatures (e.g., -> Item where Item is a Pydantic model) or via the response_model parameter (e.g., @app.post(..., response_model=Item)). This ensures returned data is validated, filtered (e.g., excluding internal or sensitive fields), and serialized according to the model, while generating precise OpenAPI documentation. It supports structures like List[Item] for arrays or unions for variant responses.[19] Best practices for Pydantic response models emphasize defining separate models for requests and responses to avoid exposing sensitive data (e.g., including password in UserIn but excluding it from UserOut). Model inheritance from a shared base model reduces duplication while preserving consistency across schemas (e.g., a UserBase with common fields extended by UserIn and UserOut). Specifying response_model in decorators enforces validation, filtering, serialization, and accurate documentation even when returning dicts or ORM objects, decoupling the return type from the output structure. Prefer explicit model design over manual exclusion via response_model_include or response_model_exclude for superior maintainability and JSON Schema precision. Options like response_model_exclude_unset=True (omit unset fields), response_model_exclude_none=True (exclude None), and response_model_exclude_defaults=True (omit default-matching values) reduce response size, especially for optional-heavy models.[34][19][35] Validation errors trigger an HTTPException with a 422 Unprocessable Entity status code, providing detailed JSON responses that include the error location (e.g., ["body", "price"]), message (e.g., "value is not a valid float"), type (e.g., "type_error.float"), and the original invalid body for debugging. This standardized handling, built on Pydantic's ValidationError, promotes robust error reporting without manual intervention.[36] These type hints yield significant benefits, including IDE autocompletion and inline documentation for parameters and returns, compatibility with static analyzers like mypy for early error detection, and reduced runtime bugs through proactive validation, ultimately streamlining development and enhancing API reliability.[7]

Asynchronous Operations

FastAPI supports asynchronous programming through the use of Python's async and await keywords, enabling developers to define endpoint functions that handle concurrent operations without blocking the event loop.[9] To implement this, path operations are declared using async def when the function needs to await I/O operations, such as database queries or external HTTP requests. For instance, a simple asynchronous endpoint might look like this:
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"Hello": "World"}
This syntax signals to the ASGI server, like Uvicorn, that the function can pause execution during awaitable calls, allowing the server to process other requests concurrently.[9] FastAPI integrates seamlessly with Python's asyncio library, which manages non-blocking I/O operations essential for web applications involving slow external resources.[9] This integration allows endpoints to perform tasks like asynchronous database interactions or API calls without halting the entire application, as await yields control back to the event loop during waits. For example, developers can use awaitable sessions from libraries compatible with asyncio, such as SQLAlchemy's asynchronous ORM features. A representative example involves querying a database asynchronously:
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
from fastapi import FastAPI, Depends

engine = create_async_engine("sqlite+aiosqlite:///./test.db")
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

async def get_db():
    async with AsyncSessionLocal() as session:
        yield session

@app.get("/items/")
async def read_items(db: AsyncSession = Depends(get_db)):
    result = await db.execute(select(Item))
    items = result.scalars().all()
    return items
Here, the await db.execute() call handles the query non-blockingly, ensuring efficient resource use. Similarly, for external API calls, FastAPI pairs well with the httpx library, which provides an asynchronous HTTP client. An example endpoint making an async request might be:
import httpx
from fastapi import FastAPI

app = FastAPI()

@app.get("/fetch-data/")
async def fetch_data():
    async with httpx.AsyncClient() as client:
        response = await client.get("https://api.example.com/data")
        return response.[json](/page/JSON)()
This approach uses await client.get() to fetch data without blocking, integrating directly into FastAPI's async model.[37] The primary benefits of FastAPI's asynchronous operations lie in handling I/O-bound tasks, where much of the time is spent waiting for external systems like databases or networks.[9] By leveraging concurrency via asyncio, FastAPI achieves higher throughput in I/O-heavy applications, processing multiple requests simultaneously without the overhead of threading or multiprocessing. This leads to improved scalability, as a single process can manage thousands of concurrent connections efficiently, making it suitable for high-traffic web APIs.[9] However, asynchronous operations in FastAPI are not ideal for CPU-bound tasks, such as intensive computations or data processing, where parallelism is needed rather than concurrency.[9] In these cases, the single-threaded event loop can become a bottleneck, and FastAPI recommends offloading such work to multiprocessing or dedicated worker processes to avoid blocking other requests.[9]

Dependency Injection

FastAPI's dependency injection system enables path operation functions to declare required components, which the framework automatically resolves and injects, promoting reusable and modular code. Dependencies are typically defined as callable functions or classes that return values needed by endpoints, such as shared resources or configuration. This mechanism is invoked using the Depends() function in parameter annotations, allowing FastAPI to execute the dependency and pass its result to the path operation before handling the request. For instance, a dependency might define a database session as def get_db(): yield session, where the session is provided before the endpoint runs and cleaned up afterward.[38] Common use cases for dependencies include managing database connections to share sessions across multiple endpoints without repetition, implementing authentication mechanisms like OAuth2 with JWT tokens to verify user credentials, caching frequently accessed data to improve performance, and enforcing rate limiting to control API request volumes. These applications leverage dependencies to encapsulate logic that would otherwise clutter individual path operations, ensuring consistent behavior throughout the application.[6][38] Key features of the system include support for hierarchical dependencies, where a dependency can itself depend on others, forming nested trees that FastAPI resolves automatically in the correct order. Results from dependencies are cached per request to avoid redundant computations, though this can be disabled with use_cache=False for specific invocations. Additionally, dependency overrides allow developers to replace dependencies during testing, such as substituting real database calls with mocks, enhancing test isolation and speed.[39][40] Dependencies execute prior to the corresponding path operation, ensuring all required resources are available, and support both synchronous and asynchronous functions for compatibility with async endpoints. Automatic cleanup is handled through the yield statement in dependency functions, which provides the value before the endpoint and executes subsequent code—such as closing connections—after the response is sent, with sub-dependencies cleaned up in reverse order. This yield-based approach mimics Python context managers internally, guaranteeing resource management even in error cases.[41] The system's advantages lie in its promotion of clean, testable code by separating concerns and reducing boilerplate, while fostering modularity through reusable components that integrate seamlessly with FastAPI's type hints and validation. By enabling easy overrides and hierarchical composition, it facilitates scalable application design and simplifies maintenance in production environments.[6][38]

Automatic OpenAPI Documentation

FastAPI automatically generates OpenAPI documentation from the application's code, leveraging Python type hints, Pydantic models, and path operation decorators to produce a JSON or YAML schema that describes the API's structure, endpoints, parameters, request/response bodies, and more.[42] This process occurs dynamically via the FastAPI class's .openapi() method, which invokes get_openapi to construct the schema based on the app's routes, defaulting to OpenAPI version 3.1.0 since FastAPI 0.99.0.[42] The schema is accessible at /openapi.json (configurable via openapi_url), ensuring it remains synchronized with the codebase without manual intervention.[43] The generated schema powers interactive user interfaces for API exploration and testing. By default, FastAPI serves Swagger UI at /docs, an open-source tool that renders the OpenAPI schema into an interactive web page allowing users to view endpoint details, execute requests with sample data, and inspect responses directly in the browser.[44] Complementing this, ReDoc is available at /redoc, providing a cleaner, three-panel documentation layout with collapsible sections for the schema, also supporting interactive "try it out" functionality.[44] Both UIs load assets from CDNs by default but can be self-hosted for production environments.[45] Customization of the documentation is achieved through metadata annotations in the code. Developers can add summaries, descriptions (supporting Markdown), tags for grouping endpoints, and external documentation links using docstrings in path operation functions and Pydantic models, as well as app-level metadata like title, version, contact, and license_info via the FastAPI constructor.[43] Security schemes, such as OAuth2 or API keys, are defined using decorators like @app.get(..., security=...) or schema extensions, integrating seamlessly into the generated docs.[43] For advanced needs, the OpenAPI schema can be overridden by customizing the .openapi() method or extending the schema post-generation, such as adding logos or modifying components.[42] FastAPI adheres to OpenAPI 3.0 and later standards, incorporating JSON Schema for model definitions to ensure compatibility with tools like OpenAPI Generator for client SDK creation, including TypeScript clients via tools such as @hey-api/openapi-ts or openapi-typescript, which enable type-safe frontend integrations with libraries like TanStack Query for automated typed queries and hooks.[6][46] This compliance extends to support for webhooks (since OpenAPI 3.1.0) and examples in request/response schemas, enhancing interoperability.[14] The primary benefits of this automatic documentation include reduced maintenance overhead, as changes to the API code immediately reflect in the docs, minimizing discrepancies between implementation and description.[6] It facilitates rapid development and collaboration by providing instantly accessible, interactive interfaces that serve as both reference and testing tools, accelerating API adoption and debugging without requiring separate documentation efforts.[6]

Advanced Capabilities

WebSockets Support

FastAPI provides native support for WebSockets, enabling real-time, bidirectional communication between clients and servers over a single, long-lived connection.[47] This feature is built on Starlette's WebSocket class, which integrates seamlessly with FastAPI's asynchronous architecture and type hints.[48] WebSockets in FastAPI are particularly suited for applications requiring low-latency updates, such as collaborative tools or live data feeds, without the overhead of repeated HTTP requests.[47] To declare a WebSocket endpoint, developers use the @app.websocket decorator followed by a path, with the endpoint function accepting a WebSocket parameter typed from fastapi. For example:
from fastapi import FastAPI, WebSocket
from fastapi.responses import HTMLResponse

app = FastAPI()

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
To handle incoming messages and disconnections gracefully, it is recommended to wrap the message receive/send loop in a try block. Catch the WebSocketDisconnect exception in an except block for graceful handling, such as logging the disconnection, removing the client from a connection manager, or notifying other connected clients. Use a finally block for reliable cleanup operations (e.g., logging connection closure or releasing resources) that execute regardless of whether an exception occurred or how the connection ended. This pattern ensures robust WebSocket endpoints, as the await websocket.receive_text() (or similar receive methods) raises WebSocketDisconnect upon client disconnection, and unexpected errors can be caught separately while still guaranteeing cleanup. Here is an example of a simple echo WebSocket endpoint with proper disconnection handling:
from fastapi import FastAPI, WebSocket, WebSocketDisconnect

app = FastAPI()

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    try:
        while True:
            data = await websocket.receive_text()
            # Process data
            await websocket.send_text(f"Echo: {data}")
    except WebSocketDisconnect:
        print("Client disconnected normally")
        # Perform graceful handling, e.g., remove from manager, notify others
    except Exception as e:
        print(f"Error: {e}")
    finally:
        print("Cleanup: Connection closed")
        # Reliable cleanup actions here
For more complex scenarios involving multiple clients, such as chat applications, implement a connection manager to track active connections, handle disconnections by removing clients, and broadcast updates to remaining participants, as demonstrated in the official FastAPI documentation.[47]

Python RAG APIs

FastAPI is employed in the construction of Retrieval-Augmented Generation (RAG) APIs within Python ecosystems, facilitating the integration of large language models with retrieval systems to improve response accuracy through external knowledge sources.[49] These APIs typically leverage semantic search techniques and vector databases, such as Qdrant or Pinecone, for efficient document indexing and querying.[50][51] Implementations often incorporate asynchronous processing via FastAPI to handle scalable retrieval operations, with examples including integrations with frameworks like LangChain for modular RAG pipelines.[51][52] Key deployment considerations encompass scalability through horizontal scaling and rate limiting, latency reduction using caching mechanisms, and security features like API authentication.[49][53] Best practices for production environments stress the importance of evaluation metrics for retrieval accuracy, continuous monitoring with tools such as Prometheus and Grafana, and iterative refinements based on performance data to ensure system reliability.[49][53] # Handle connection

This setup allows the endpoint to manage incoming connections at the specified route.[](https://fastapi.tiangolo.com/advanced/websockets/) The `WebSocket` instance, derived from Starlette, exposes methods for managing the connection lifecycle: `accept()` to establish the connection (optionally with a subprotocol or headers), `receive_text()`, `receive_json()`, or `receive_bytes()` to asynchronously retrieve client messages, `send_text()`, `send_json()`, or `send_bytes()` to transmit responses, and `close(code=1000, reason=None)` to terminate the session gracefully.[](https://www.starlette.dev/websockets/) These methods support both text and binary data transmission, with JSON handling leveraging Python's built-in serialization for structured payloads.[](https://www.starlette.dev/websockets/)

FastAPI enhances [WebSocket](/page/WebSocket) functionality through integration with its [dependency injection](/page/Dependency_injection) system and Pydantic models. Dependencies, such as [authentication](/page/Authentication) checks via `Depends`, can be injected into WebSocket endpoints to secure connections, for instance, by validating query parameters or cookies before acceptance.[](https://fastapi.tiangolo.com/advanced/websockets/) Pydantic models enable automatic validation of received [JSON](/page/JSON) messages; by type-hinting the return of `receive_json()` with a Pydantic BaseModel, FastAPI parses and validates the data against the schema, raising validation errors if mismatched.[](https://fastapi.tiangolo.com/advanced/websockets/) This combination ensures type-safe, secure handling of real-time data exchanges.

Common use cases for FastAPI WebSockets include building chat applications for multi-user messaging, live notifications for dynamic updates like stock tickers or social feeds, and streaming services for continuous data flows such as sensor readings or video metadata.[](https://fastapi.tiangolo.com/advanced/websockets/) In a chat scenario, a server might broadcast messages to connected clients upon receipt from one user.

Error handling in FastAPI WebSockets primarily involves catching the `WebSocketDisconnect` exception, raised by Starlette when a client terminates the connection unexpectedly, allowing the server to clean up resources or log the event.[](https://fastapi.tiangolo.com/advanced/websockets/) For managing multiple concurrent connections, FastAPI applications often implement a custom `ConnectionManager` class that tracks active WebSocket instances in a set and provides methods like `connect()`, `disconnect()`, and `broadcast()` to send messages to all or selected clients, ensuring efficient group communication without direct endpoint modifications.[](https://fastapi.tiangolo.com/advanced/websockets/) This pattern supports scalable real-time features while maintaining FastAPI's emphasis on simplicity and performance.[](https://fastapi.tiangolo.com/advanced/websockets/)

### Background Tasks

FastAPI provides a mechanism for executing background tasks after an HTTP response has been sent to the client, allowing developers to offload non-critical operations without blocking the main request-response cycle. This feature is implemented through the `BackgroundTasks` class, which is imported from FastAPI and can be injected as a parameter into path operation functions. By calling `background_tasks.add_task()` within an endpoint, users can schedule a function—either synchronous or asynchronous—along with its arguments to run concurrently using Python's `asyncio` event loop. These tasks are particularly suited for operations that do not require immediate completion, ensuring the API remains responsive.[](https://fastapi.tiangolo.com/tutorial/background-tasks/)

A typical usage involves declaring the `BackgroundTasks` dependency in an endpoint and adding tasks before returning the response. For instance, to simulate sending a notification without delaying the user:

```python
from fastapi import BackgroundTasks, FastAPI

app = FastAPI()

def write_notification(email: str, message: str = ""):
    with open("log.txt", "w") as log_file:
        log_file.write(f"Notification for {email}: {message}")

@app.post("/send-notification/{email}")
async def send_notification(email: str, background_tasks: BackgroundTasks):
    background_tasks.add_task(write_notification, email, message="some notification")
    return {"message": "Notification sent in the background"}
In this example, the write_notification function executes after the JSON response {"message": "Notification sent in the background"} is delivered, preventing any delay from file I/O operations. Background tasks support both regular functions and async functions, with the latter leveraging asyncio for further concurrency if needed. This approach integrates seamlessly with FastAPI's dependency injection system, where BackgroundTasks can be used alongside other dependencies in path operations or sub-dependencies.[54] Common applications of background tasks include sending email notifications, logging events to files or databases, and performing lightweight data processing such as resizing images uploaded via the API, all of which can occur post-response to maintain low latency for the end user. For example, in an image upload endpoint, a task could handle thumbnail generation asynchronously after acknowledging the upload with an HTTP 201 status. However, these tasks operate within the same process as the FastAPI application and do not have direct access to the original request or response objects, as they execute after the response cycle completes. Developers should ensure task functions are self-contained, passing any necessary data via arguments to add_task(). While suitable for small, non-blocking workloads, for more resource-intensive or distributed tasks, FastAPI documentation recommends integrating external systems like Celery with message brokers such as RabbitMQ or Redis.[54][55]

Security and Authentication

FastAPI provides a suite of built-in security utilities in the fastapi.[security](/page/Security) module to implement authentication and authorization schemes that conform to OpenAPI standards, enabling seamless integration with automatic documentation.[56] These tools support common protocols such as HTTP Basic, OAuth2, and API key-based authentication, allowing developers to declare security requirements at the path operation level.[57] One fundamental authentication method is HTTP Basic, which requires clients to provide a username and password in the Authorization header; if absent, FastAPI returns a 401 Unauthorized response with a WWW-Authenticate: Basic challenge.[58] Implementation involves the HTTPBasic class and dependency injection via Depends, as shown in this example:
from fastapi import Depends, FastAPI
from fastapi.security import HTTPBasic, HTTPBasicCredentials

app = FastAPI()
security = HTTPBasic()

@app.get("/users/me")
def read_current_user(credentials: HTTPBasicCredentials = Depends(security)):
    if credentials.username == "stanleyjobson" and credentials.password == "swordfish":
        return {"username": credentials.username}
    raise HTTPException(status_code=401, detail="Invalid credentials")
For secure validation, use secrets.compare_digest to compare credentials and mitigate timing attacks.[58] OAuth2 support in FastAPI includes flows like password-based authentication, where clients submit credentials to a /token endpoint to obtain a bearer token, which is then used in subsequent requests via the Authorization header.[59] The OAuth2PasswordBearer utility defines the scheme, integrating with Depends for token extraction:
from fastapi import Depends, FastAPI
from fastapi.security import OAuth2PasswordBearer

app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

@app.get("/items/")
async def read_items(token: str = Depends(oauth2_scheme)):
    return {"token": token}
This setup automatically generates interactive OpenAPI documentation with an "Authorize" button for testing.[59] API key authentication is facilitated through classes like APIKeyHeader, APIKeyQuery, and APIKeyCookie, which extract keys from headers, query parameters, or cookies, respectively, and enforce presence via Depends.[56] For instance, header-based API keys use:
from fastapi import Depends, FastAPI
from fastapi.security import APIKeyHeader

app = FastAPI()
header_scheme = APIKeyHeader(name="x-api-key")

@app.get("/items/")
async def read_items(key: str = Depends(header_scheme)):
    if key != "valid-key":
        raise HTTPException(status_code=403, detail="Invalid API key")
    return {"key": key}
These schemes support custom validation logic within the dependency.[56] For enhanced security in OAuth2 flows, FastAPI integrates with JSON Web Tokens (JWT) using libraries like PyJWT for token creation and validation, combined with Passlib for secure password hashing (e.g., using Argon2).[60] Tokens are generated with an expiration time and a secret key, then decoded in a get_current_user dependency:
from datetime import timedelta
from fastapi import Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
from passlib.context import CryptContext

SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

def create_access_token(data: dict, expires_delta: timedelta):
    to_encode = data.copy()
    expire = datetime.utcnow() + expires_delta
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=[ALGORITHM](/page/Algorithm))
    return encoded_jwt

def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(status_code=401, detail="Invalid credentials")
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
    except JWTError:
        raise credentials_exception
    return username
Best practices include using a strong, randomly generated SECRET_KEY (e.g., via openssl rand -hex 32) and short token expiration periods, such as 30 minutes.[60] FastAPI's dependency injection system applies directly to security contexts, allowing reusable authentication logic across endpoints without duplicating code.[57] Input sanitization is achieved through Pydantic models, which validate and coerce data types, reducing risks from malformed inputs.[57] To protect against cross-origin request forgery (CORS) vulnerabilities, FastAPI offers CORSMiddleware for configuring allowed origins, methods, and headers; for security, explicitly list origins instead of using wildcards, especially with credentials enabled.[61] Rate limiting, essential for preventing abuse, is implemented via extensions like SlowAPI, which uses Redis for distributed throttling and integrates as middleware or dependencies.[62] Common protections in FastAPI applications include defense against SQL injection through parameterized queries in ORMs like SQLAlchemy, XSS mitigation via JSON-only responses that browsers do not execute as scripts, and reduced CSRF exposure in stateless APIs that rely on tokens rather than sessions.[57] Always deploy over HTTPS to encrypt traffic and protect credentials in transit.

Usage and Examples

Installation and Setup

FastAPI requires Python 3.8 or higher to ensure compatibility with its dependencies, such as Pydantic for data validation.[8][63] To isolate project dependencies and avoid conflicts with system-wide packages, it is recommended to set up a virtual environment using tools like venv (built into Python) or Conda.[64] For venv, first create a project directory, such as mkdir myproject && cd myproject, then initialize the environment with python -m venv .venv. Activate it on Linux/macOS using source .venv/bin/activate or on Windows with .venv\Scripts\Activate.ps1. Upgrade pip within the environment via python -m pip install --upgrade pip to ensure the latest package installer.[64] With Conda, create an environment using conda create -n myenv python=3.8 and activate it with conda activate myenv, followed by upgrading pip as above.[64] Once the virtual environment is active, install FastAPI with its standard dependencies for a complete setup, including the Uvicorn ASGI server and CLI tools: pip install "fastapi[standard]".[63] For a minimal installation without extras, use pip install fastapi followed by pip install "uvicorn[standard]" to enable running the application.[63] Prepare the project structure by creating a file named main.py in the project directory. In this file, import FastAPI and instantiate the application:
from fastapi import FastAPI

app = FastAPI()
To run the application in development mode, use the command uvicorn main:app --reload from the project directory, which starts the server at http://127.0.0.1:8000 and enables auto-reloading on code changes.[63] Alternatively, if the standard dependencies are installed, fastapi dev main.py provides similar functionality with additional development features.[63] For optional extensions, install packages like SQLAlchemy for database integration via pip install sqlalchemy or pytest for testing with pip install pytest. No additional installations are required for automatic OpenAPI documentation, as it is built into FastAPI.[63] Verify the setup by accessing the interactive API documentation at http://127.0.0.1:8000/docs in a web browser after starting the server; this displays the Swagger UI for the application's endpoints.[63] If the page loads successfully, the installation and basic setup are complete.[63]

Project Structure Best Practices (2026)

As of February 2026, there is no single "best" FastAPI project structure—it depends on project size, team preferences, and complexity. For small to medium projects, the official FastAPI documentation recommends a modular structure using APIRouters in separate files.[65] Official basic modular structure (from FastAPI docs):
app/
├── __init__.py
├── main.py
├── dependencies.py
└── routers/
    ├── __init__.py
    ├── items.py
    └── users.py
For larger, scalable, production-ready applications, a domain-driven design is widely recommended in 2026 community resources and articles, organizing code by business domains (e.g., auth, users, posts) rather than technical layers. This promotes maintainability, testability, and scalability.[66][67] Popular domain-driven structure (from updated 2026 community best practices):
src/
├── auth/
│   ├── router.py
│   ├── schemas.py
│   ├── models.py
│   ├── service.py
│   ├── dependencies.py
│   └── exceptions.py
├── posts/
│   └── (similar files)
├── config.py
├── database.py
└── main.py
This groups related files (routers, schemas, models, business logic) per domain, with global shared code at the src root.

Basic API Example

A basic FastAPI application can be created by importing the FastAPI class and instantiating it to define the app instance.[63] Path parameters are declared in the route by enclosing the variable in curly braces, such as {item_id} for a GET endpoint that retrieves an item by ID.[68] Type hints, like int for item_id, enable automatic validation, ensuring the parameter is an integer or returning a 422 Unprocessable Entity error with details if invalid (e.g., providing a string like "foo" instead of a number).[68] Query parameters, such as an optional q string, are added as function arguments with defaults (e.g., None), allowing flexible requests like filtering.[69] The following complete code example defines a simple app with a GET endpoint at /items/{item_id} that accepts an integer path parameter and an optional query parameter:
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str | None = None):
    if q:
        return {"item_id": item_id, "q": q}
    return {"item_id": item_id}
Note for development: To enable detailed tracebacks in the JSON error response body for unhandled exceptions (such as 500 Internal Server Errors), particularly when Uvicorn's default logging may suppress detailed server-side logs, initialize the app with debug=True:
app = FastAPI(debug=True)
This setting, inherited from the underlying Starlette framework, includes full error tracebacks in the response, facilitating easier debugging without relying solely on console or server logs. It should be disabled (default: False) in production to avoid exposing sensitive information.[70] This endpoint returns JSON responses, such as {"item_id": 5} for a request to http://127.0.0.1:8000/items/5 or {"item_id": 5, "q": "search"} when including ?q=search.[68][69] To run the application, save the code as main.py and execute fastapi dev main.py in the terminal (assuming FastAPI and Uvicorn are installed).[63] The server starts at http://127.0.0.1:8000. Interactive documentation is automatically available at http://127.0.0.1:8000/docs (Swagger UI), where endpoints can be tested directly by entering parameters and executing requests, revealing JSON outputs and validation errors (e.g., a 422 error for non-integer item_id with a message like "value is not a valid integer").[63] Alternatively, requests can be tested via tools like curl, for example: curl "http://127.0.0.1:8000/items/5?q=test", which yields the expected JSON.[69] As an extension, a POST endpoint can be added to create items using a Pydantic model for request body validation. The model defines required fields like name (string) and price (float), with optional description and tax.[18] The updated code includes:
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

@app.post("/items/")
async def create_item(item: Item):
    return item
A request to http://127.0.0.1:8000/items/ with JSON body {"name": "Foo", "price": 50.2} returns the validated item as JSON, while invalid data (e.g., missing name or non-numeric price) triggers a 422 error detailing the validation failure.[18] This can be tested in the /docs UI by selecting the POST endpoint, inputting the body, and executing.

Advanced Example with Dependencies

In this advanced example, a user registration endpoint demonstrates the integration of FastAPI's dependency injection for managing a fake in-memory database (simulating a session), asynchronous execution, Pydantic models for input validation, OAuth2-based authentication patterns (adapted for post-registration token issuance), and background tasks for non-blocking operations like email notifications. This setup creates a realistic API for handling user sign-ups securely and efficiently, building on core FastAPI features to handle shared resources and side effects without blocking the main response.[71][60][54] For this example, additionally install the required packages: pip install "passlib[bcrypt]" "pyjwt". The following complete code example uses a dictionary-based fake database (fake_users_db) to store users, mimicking a persistent session without requiring an external database like SQLAlchemy. It incorporates a dependency function get_db to inject the database reference into the endpoint, ensuring thread-safe access in a real-world async environment. Pydantic's UserCreate model validates incoming data via the Pydantic model and type hints, while password hashing (using passlib) and JWT token generation (via PyJWT) secure the process. A background task sends a confirmation email after successful registration, running asynchronously after the HTTP response is returned. OAuth2 elements are included for immediate token issuance upon registration, aligning with standard authentication flows.[38][60][54]
import datetime
from datetime import timedelta
from typing import Annotated, Dict
import jwt
from fastapi import Depends, FastAPI, HTTPException, BackgroundTasks
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from pydantic import BaseModel
from passlib.context import CryptContext

app = FastAPI()

Example: D&D-Style Game Backend with SQLModel and PostgreSQL

This example demonstrates building a FastAPI backend for a D&D-style game, allowing creation and management of universes (containing multiple maps) using SQLModel for ORM interactions and PostgreSQL for relational storage. Complex map data such as grid layouts and entities can be stored in JSONB columns for flexibility. The example follows official FastAPI and SQLModel patterns for relational databases and CRUD operations.[71][72] Install the required dependencies:
pip install fastapi uvicorn sqlmodel psycopg2-binary
For asynchronous database operations, replace psycopg2-binary with asyncpg and use asynchronous engine/session patterns. Define the SQLModel table models, including a one-to-many relationship between Universe and Map, and JSONB for grid_data:
from typing import Optional
from sqlmodel import SQLModel, Field, Relationship, Session, select
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy import Column

class Universe(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    description: Optional[str] = None
    owner_id: Optional[int] = Field(default=None)  # foreign key to users table for ownership
    maps: list["Map"] = Relationship(back_populates="universe")

class Map(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    description: Optional[str] = None
    universe_id: int = Field(foreign_key="universe.id")
    grid_data: dict = Field(sa_column=Column(JSONB), default_factory=dict)
    universe: Universe = Relationship(back_populates="maps")
Separate Pydantic models are recommended for input/output to control validation and exposure:
class UniverseCreate(SQLModel):
    name: str
    description: Optional[str] = None

class UniversePublic(SQLModel):
    id: int
    name: str
    description: Optional[str] = None

class MapCreate(SQLModel):
    name: str
    description: Optional[str] = None
    grid_data: dict = {}

class MapPublic(SQLModel):
    id: int
    name: str
    description: Optional[str] = None
    universe_id: int
    grid_data: dict
Set up the database engine (replace with your PostgreSQL connection string):
from sqlmodel import create_engine

DATABASE_URL = "postgresql://user:password@localhost/dbname"
engine = create_engine(DATABASE_URL)
Define a dependency for database sessions:
from fastapi import Depends

def get_session() -> Session:
    with Session(engine) as session:
        yield session
To add user ownership, integrate authentication (e.g., OAuth2 with JWT as described in the Security and Authentication section). Inject a current_user dependency into endpoints and set/filter by owner_id == current_user.id. For complex spatial features, consider GeoAlchemy2 extensions.[60] Implement async CRUD endpoints where performance benefits (using async def and async session if configured with asyncpg):
  • POST /universes/ to create a universe (set owner_id from current_user).
  • GET /universes/ to list universes (filter by owner_id).
  • GET /universes/{id} to retrieve a specific universe.
  • Similar CRUD for /maps/, with filtering by universe_id and ownership checks.
Run the application with:
uvicorn main:app --reload
Access the interactive OpenAPI documentation at /docs.

Deployment

For learners who have followed the official FastAPI tutorial to build a basic API application, Dockerizing that app using the official Docker deployment guide is a recommended next step to gain practical experience with containerization and deployment. This project-based approach solidifies learning through hands-on practice.[11] FastAPI applications can be deployed in production using containerization with Docker, which facilitates consistent environments across development and production setups. For self-hosted deployments, Docker images can be run on virtual private servers (VPS) from providers such as DigitalOcean or Hetzner, either directly using Docker or orchestrated with Kubernetes for enhanced scalability and management.[11][73][74] As of 2026, key best practices for Dockerizing FastAPI applications include using slim Python base images (e.g., python:3.14-slim) and multi-stage builds for smaller, secure production images; optimizing Dockerfile layer caching by copying requirements.txt first and using a .dockerignore file to exclude unnecessary files (e.g., .git, pycache, venv/); managing configuration via environment variables and Pydantic Settings for security and portability; implementing health checks (e.g., /health endpoint) and database readiness checks in Docker Compose; configuring structured logging and proper signal handling for clean shutdowns via exec-form CMD; scaling with Uvicorn workers (via --workers), reverse proxies (e.g., Nginx), and separate migration containers; and using Docker Compose for development with live reloading and production-like setups.[11] A recommended multi-stage Dockerfile for a FastAPI application, adapted from official guidance and community best practices, is as follows:

### Testing Form-Data and File Upload Endpoints in Postman

FastAPI endpoints that expect form data (declared with `Form()`) or file uploads (declared with `UploadFile` or `File()`) require the `python-multipart` package to parse incoming requests:

```bash
pip install python-multipart
FastAPI parses multipart/form-data and application/x-www-form-urlencoded content types when parameters are declared with Form(). The form-data encoding is required for requests including files and is more versatile overall.[75][76] To test such endpoints in Postman:
  1. Create a new request in Postman, typically a POST request to the endpoint URL.
  2. In the Body tab, select "form-data" (instead of "raw" or "JSON").
  3. Add form fields: enter the parameter name as the key and the value as the value. For file uploads (UploadFile), set the type to "File" and select the file.
  4. Postman automatically sets the Content-Type header to multipart/form-data.
  5. Send the request.
This approach enables verification of form-handling and file-upload functionality directly in Postman, complementing the interactive OpenAPI documentation at /docs.[75]

Build stage

FROM python:3.14-slim AS builder WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir --upgrade -r requirements.txt

Runtime stage

FROM python:3.14-slim WORKDIR /app COPY --from=builder /usr/local/lib/python3.14/site-packages /usr/local/lib/python3.14/site-packages COPY --from=builder /usr/local/bin /usr/local/bin COPY . .

Optional health check (assuming a /health endpoint is implemented in the app)

HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3
CMD curl -f http://localhost:80/health || exit 1
EXPOSE 80 CMD ["fastapi", "run", "main.py", "--port", "80"]

This Dockerfile leverages multi-stage builds to minimize image size and attack surface by excluding build-time dependencies, optimizes caching by installing dependencies before copying application code, and uses the FastAPI CLI for execution, ensuring proper signal handling and lifespan events through the exec form of CMD. In production, add options like --workers 4 for multiple processes within a container or --proxy-headers when behind a reverse proxy. Create a .dockerignore file to further reduce build context size and improve security. Implement a /health endpoint in your FastAPI application for reliable health checking.[](https://fastapi.tiangolo.com/deployment/docker/)

In production environments, configuration values such as database connections or secret keys can be overridden via environment variables, often managed through .env files or platform-specific settings, and preferably loaded using Pydantic Settings for type-safe, validated configuration. Docker Compose is commonly utilized to orchestrate the FastAPI container alongside supporting infrastructure services like databases, with healthchecks for the application and readiness conditions (e.g., depends_on with service_healthy) for database services. For distributed deployments, Kubernetes provides tools for replication, load balancing, automatic scaling across multiple containers, and init containers or separate migration containers for database schema updates.[](https://fastapi.tiangolo.com/deployment/docker/)[](https://www.digitalocean.com/community/tutorials/create-fastapi-app-using-docker-compose)

Additionally, FastAPI Cloud is an official managed deployment platform built by the same author and team behind FastAPI. It enables deployment of FastAPI applications with a single command (`fastapi deploy`), providing features such as automatic HTTPS, replication, autoscaling based on request volume (including scaling down to zero), environment variable management, custom domains, and built-in observability. FastAPI Cloud is the primary sponsor and funding provider for the *FastAPI and friends* open source projects. The service is currently in private beta, with access granted via a waiting list.[](https://fastapi.tiangolo.com/deployment/fastapicloud/)[](https://fastapicloud.com/)
# Fake in-memory database
fake_users_db: Dict[str, Dict] = {"users": []}

# Security settings (load SECRET_KEY from environment variable in production)
SECRET_KEY = "your-secret-key"  # In practice, use os.getenv("SECRET_KEY")
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

class Token(BaseModel):
    access_token: str
    token_type: str

class TokenData(BaseModel):
    username: str | None = None

class UserBase(BaseModel):
    username: str
    email: str | None = None

class UserCreate(UserBase):
    password: str

class User(UserBase):
    id: int
    is_active: bool = True

    model_config = {"from_attributes": True}

# Dependency for database session (fake DB injection)
def get_db() -> Dict[str, Dict]:
    return fake_users_db

DBDep = Annotated[Dict[str, Dict], Depends(get_db)]

# Background task for email sending
def send_welcome_email(email: str, username: str):
    # Simulate email sending (e.g., integrate with SMTP in production)
    print(f"Welcome email sent to {email} for user {username}")

# Utility functions for security
def verify_password(plain_password: str, hashed_password: str) -> bool:
    return pwd_context.verify(plain_password, hashed_password)

def get_password_hash(password: str) -> str:
    return pwd_context.hash(password)

def create_access_token(data: dict, expires_delta: timedelta | None = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.datetime.utcnow() + expires_delta
    else:
        expire = datetime.datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

# Async registration endpoint with dependencies, validation, and background task
@app.post("/register", response_model=Token)
async def register_user(
    background_tasks: BackgroundTasks,
    user: UserCreate,  # Pydantic validation via the model and type hints
    db: DBDep  # Database dependency
):
    # Error handling: Check for existing username
    if any(u["username"] == user.username for u in db["users"]):
        raise HTTPException(
            status_code=400,
            detail="Username already registered"
        )
    
    # Hash password and create user
    hashed_password = get_password_hash(user.password)
    user_dict = {
        "id": len(db["users"]) + 1,
        "username": user.username,
        "email": user.email,
        "hashed_password": hashed_password,
        "is_active": True
    }
    db["users"].append(user_dict)
    
    # Add background task for email
    background_tasks.add_task(send_welcome_email, user.email, user.username)
    
    # Issue OAuth2 access token
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}
This example breaks down key components as follows. The get_db dependency provides a shared fake database reference, ensuring it's injected cleanly into the endpoint without global state pollution, which supports scalability in larger applications.[38] The UserCreate Pydantic model enforces validation rules (e.g., required fields like password with type constraints), automatically generating OpenAPI schemas and handling serialization/deserialization. Error handling uses HTTPException to return standardized HTTP responses (e.g., 400 for conflicts), integrated seamlessly with FastAPI's exception handlers for consistent API behavior. The async nature of the endpoint allows non-blocking I/O, while the background task decouples email sending from the response cycle, preventing delays in user feedback.[71][60][54] For testing, FastAPI's automatic OpenAPI documentation at /docs enables interactive exploration: users can submit registration requests via the Swagger UI, validating inputs against the Pydantic model and observing background task effects (e.g., console logs simulating emails). For automated unit tests, use pytest with FastAPI's TestClient to simulate requests, including dependency overrides for the fake DB to ensure isolation. An example test might verify successful registration returns a 200 status with a valid token, while duplicate usernames trigger a 400 error.[77] Best practices in this setup include loading sensitive values like SECRET_KEY from environment variables (e.g., via python-dotenv) to avoid hardcoding, enhancing security in deployment. Organize code modularly: place models in a models.py file, dependencies and utilities in dependencies.py, and the main app in main.py, promoting maintainability as the API grows. This structure aligns with FastAPI's emphasis on clean, testable code while integrating advanced features like OAuth2 for secure token handling, as detailed in dedicated security patterns.[60][78]

Performance and Ecosystem

Benchmarks and Performance

FastAPI demonstrates exceptional performance among Python web frameworks, particularly in asynchronous workloads, as evidenced by its consistent high rankings in the TechEmpower Framework Benchmarks. In these independent tests, FastAPI applications running under Uvicorn rank among the fastest Python frameworks available, particularly for asynchronous workloads.[4][79] For instance, on standard hardware configurations, optimized FastAPI endpoints can achieve over 1,000,000 requests per second in plaintext scenarios, as of Round 23 (2025).[33] In database query tests, it handles around 36,000 requests per second for single queries.[80] In the Fortunes test with PostgreSQL, which involves fetching rows from the database, adding a server message, sorting the results, and rendering an HTML template, FastAPI achieves approximately 109,000 requests per second, while the Node.js-based Fastify framework reaches approximately 266,000 requests per second.[81] The framework's speed stems from several key architectural choices. Its reliance on asynchronous I/O via the ASGI standard enables non-blocking handling of concurrent requests, allowing a single process to manage thousands of connections without thread overhead. Additionally, FastAPI builds on Starlette's lightweight foundation, which introduces minimal processing overhead for routing and middleware, while Pydantic's type hint-based validation and serialization leverages Rust-compiled components for rapid data handling without sacrificing developer productivity. These elements collectively reduce latency and boost throughput compared to traditional synchronous frameworks like Flask and Django, which rely on blocking operations and thus scale less effectively under load.[4] To further optimize FastAPI applications, developers can implement several proven techniques. Using uvloop, a high-performance drop-in replacement for the standard asyncio event loop implemented in Cython, can yield up to 20-30% improvements in I/O-bound tasks by enhancing the efficiency of the event loop's polling mechanisms. Deploying with multiple Uvicorn workers—typically matching the number of CPU cores—enables parallel processing for CPU-intensive operations, while connection pooling for databases (e.g., via asyncpg for PostgreSQL) minimizes overhead from repeated connections. Critically, avoiding synchronous code within async endpoints prevents blocking the event loop, ensuring sustained performance; for example, replacing blocking database calls with their asynchronous counterparts can double throughput in query-heavy applications. As of 2025, FastAPI benefits from enhancements in Python 3.12 and later versions, including faster startup times through optimized module loading and improved async task grouping, contributing to reduced cold-start latency in serverless environments.[82] These updates, combined with FastAPI's mature ecosystem, position it as a scalable choice for production APIs handling diverse workloads.[83]

Comparisons with Other Frameworks

FastAPI distinguishes itself from Flask primarily through its native asynchronous support and automatic documentation generation, enabling higher concurrency and easier API maintenance compared to Flask's synchronous, minimalistic design. While Flask excels in simplicity and flexibility for small-scale web applications, it requires third-party extensions like Flask-RESTX for data validation and OpenAPI documentation, which FastAPI provides out-of-the-box via Pydantic and Starlette.[84][85] FastAPI's reliance on Python type hints also reduces runtime errors during development, a feature absent in Flask, though Flask's maturity offers broader plugin availability for extensions.[86] In contrast to Django REST Framework (DRF), FastAPI is lighter and more API-centric, avoiding Django's full-stack "batteries-included" approach that includes an ORM and admin interface suited for complex web applications. DRF integrates seamlessly with Django's ecosystem for authentication, serialization, and caching but lacks native async support without additional configuration, making it slower for high-throughput APIs.[87][86] FastAPI's automatic interactive documentation via Swagger UI and ReDoc outperforms DRF's browsable APIs in developer productivity, though DRF benefits from Django's larger community and security features for enterprise-scale projects.[84][88] Compared to Bottle and Sanic, FastAPI offers superior data validation and documentation while maintaining comparable speed, as both are lightweight async frameworks. Bottle, a synchronous microframework, provides simplicity for standalone APIs but lacks async capabilities and built-in validation, resulting in manual handling of requests and errors.[88] Sanic, like FastAPI, supports asyncio for high performance and includes WebSocket handling, yet it falls short in automatic OpenAPI generation and type-based validation, requiring more boilerplate code.[84] Benchmarks show FastAPI (on Uvicorn) handling requests efficiently alongside Sanic, but with added features that enhance API reliability without significant overhead.[4] Compared to Node.js frameworks such as Express and Fastify, FastAPI delivers strong asynchronous performance through the ASGI standard with Starlette and Uvicorn. According to the TechEmpower Framework Benchmarks Round 23 (released February 2025), in the Fortunes test with PostgreSQL, Fastify achieves approximately 265,826 requests per second, while FastAPI reaches 109,166 RPS. As of early 2026, there is no definitive winner between FastAPI (Python) and Node.js frameworks, with performance varying by test conditions and implementation. FastAPI excels in developer productivity with automatic OpenAPI documentation, type safety via Pydantic, and strong async support, making it ideal for data- and ML-heavy applications. Node.js frameworks shine in real-time applications, benefit from the massive npm ecosystem, and offer full-stack JavaScript consistency. Go frameworks often outperform both for raw speed, but FastAPI is comparable to Node.js for many I/O-bound tasks and is preferred by Python teams. The choice depends on team expertise (Python vs JavaScript), use case (real-time vs data-intensive), and ecosystem needs.[81][89][4] FastAPI and NATS serve fundamentally different purposes and are not direct alternatives. FastAPI is a Python web framework for building high-performance RESTful APIs over HTTP, with features like automatic OpenAPI documentation, data validation using Pydantic, and async support.[1] NATS is a lightweight, high-performance messaging system (broker) for distributed systems, supporting pub/sub, request-reply, queuing, and persistence via JetStream, enabling decoupled, event-driven communication between services.[90] They are complementary rather than competitive: use FastAPI when building synchronous or async HTTP-based APIs and web services, and NATS for asynchronous messaging, microservices decoupling, event-driven architectures, or high-throughput inter-service communication without relying on HTTP. Similar message brokers such as RabbitMQ and Kafka can be employed for comparable asynchronous, event-driven patterns. Synchronous communication is typically achieved through direct HTTP/REST API calls, with asynchronous clients like httpx preferred to maintain non-blocking behavior in FastAPI applications.[91][92] FastAPI applications can integrate with NATS using the nats-py client for internal messaging while exposing HTTP endpoints externally. These patterns leverage FastAPI's asynchronous capabilities and align with general microservices best practices, including the use of API gateways for external access and service discovery for dynamic endpoint resolution. No direct performance or feature comparison exists because they operate at different layers (HTTP API vs messaging middleware).[93] FastAPI is preferable for microservices, data-intensive APIs, and real-time applications where async processing and automatic documentation accelerate development, particularly in Python-centric environments like AI/ML.[87][85] FastAPI's suitability for backend development in AI-integrated applications stems from its asynchronous support, which enables efficient handling of concurrent tasks such as real-time data processing and model inferences. The integration with Pydantic provides robust validation and serialization of complex data structures, facilitating the parsing of structured formats like JSON for agent configurations. Furthermore, FastAPI simplifies the implementation of webhooks, enabling seamless real-time integrations with AI services and external systems.[94][95] In contrast, opt for Flask or Bottle for lightweight prototypes, DRF for full-featured web backends, or Express for JavaScript ecosystems requiring extensive middleware.[86][88]

Adoption and Popularity

FastAPI has seen rapid adoption in the Python ecosystem. According to the 2025 JetBrains Python Developer Survey, FastAPI usage among Python developers increased from 29% to 38% in one year, marking a significant year-over-year growth of about 31% and positioning it as one of the fastest-growing web frameworks. By late 2024 to early 2025, FastAPI surpassed Flask in GitHub stars (reaching over 78,900 by some reports). This growth reflects the maturation of Python's async ecosystem since around 2022–2023, with improvements in async database drivers, uvloop integration, and Pydantic v2 performance, making FastAPI highly competitive with Node.js for I/O-bound CRUD applications with heavy validation and business logic, often within 10–40% in benchmarks while offering superior developer experience.[83]

Community and Extensions

The FastAPI community is active and collaborative, centered around its official GitHub repository, which hosts the source code and serves as the primary hub for development discussions and issue tracking. Contributions are encouraged through pull requests (PRs), with guidelines emphasizing code formatting, testing for coverage, and documentation updates in Markdown; developers can set up a local environment using editable installs and scripts for testing and docs preview.[96] The community also engages via a dedicated Discord server for real-time discussions, support, and sharing experiences among users and contributors. FastAPI benefits from a range of extensions that enhance its core functionality, including FastAPI Users, a customizable library for user registration, authentication, and management supporting JWT, OAuth2, and database backends.[97] Another notable extension is SQLAdmin, which provides an admin interface for SQLAlchemy models, integrating seamlessly with FastAPI for both synchronous and asynchronous database engines to enable quick CRUD operations and model visualization.[98] Third-party integrations expand FastAPI's ecosystem, such as Tortoise-ORM, an asynchronous ORM that pairs with FastAPI for efficient database interactions in API templates.[99] For testing, the built-in TestClient facilitates HTTP client simulation, while extensions like pytest-fastapi build on it for comprehensive API testing suites. Deployment options include serverless architectures on AWS Lambda, where FastAPI apps can be containerized with adapters like Mangum to handle API Gateway requests, enabling scalable inference endpoints for machine learning models.[100] Key tools in the ecosystem include SQLModel, a library combining SQLAlchemy's ORM capabilities with Pydantic's data validation, allowing developers to define database models as Pydantic classes for type-safe FastAPI integrations. Full-stack development is supported through templates like the official Full Stack FastAPI Template, which pairs FastAPI with React (using TypeScript, Vite, and Chakra UI) for frontend-backend applications, including PostgreSQL, Docker, and JWT authentication.[101] Similar community templates exist for Vue.js, such as fullstack-vue-fastapi-template, integrating Vite and Bun/Node.js for rapid prototyping of interactive UIs with FastAPI backends.[102] Looking ahead, FastAPI's ecosystem in 2025 emphasizes integrations for AI endpoints, exemplified by libraries like FastAPI-MCP, which simplifies connecting FastAPI apps to AI agents for enhanced model serving and automation.[103] Serverless deployments continue to gain traction, aligning with the framework's asynchronous strengths to support scalable, cost-efficient API hosting in cloud environments.[83]

References

User Avatar
No comments yet.