404 Not Found

404 Not Found


nginx

An Introduction to FastAPI — Why It's the Next-Generation Python Web Framework

If Flask is a versatile Swiss Army knife and Django is a fully equipped SUV, then FastAPI is an electric supercar—it accelerates quickly, is energy-efficient, and comes with an automatically generated dashboard.

1. What You'll Learn


2. Alice's True Story

(1) Pain Point: The synchronization framework cannot handle millions of requests

Alice is a backend engineer building PriceTracker—a SaaS price-tracking API for an e-commerce platform—that needs to handle real-time queries for millions of product prices. She initially built a prototype using Flask, but when concurrent requests exceeded 1,000 QPS, the synchronous WSGI model caused each request to queue up, and the P99 latency skyrocketed to 3,000 ms. Bob (a front-end engineer) complained about slow page loading, and Charlie (DevOps) said the cost of horizontal scaling was too high.

(2) The FastAPI Solution

FastAPI is based on the ASGI asynchronous protocol and can handle thousands of concurrent connections with a single process. Type hints automatically generate OpenAPI documentation and validate request data, so Alice doesn't need to write validation code or documentation by hand.

PYTHON
from fastapi import FastAPI

app = FastAPI()

@app.get("/products/{product_id}")
async def get_product(product_id: int):
    # Type hint automatically validates & generates docs
    return {"product_id": product_id, "name": "Widget"}

(3) Revenue

After migrating to FastAPI, PriceTracker's single-node QPS increased from 500 to over 4,000, P99 latency dropped to 50 ms, Bob's front-end page loaded 5 times faster, and Charlie's server costs were reduced by 60%.


3. ASGI and WSGI: Asynchronous Is the Future

(1) WSGI Synchronization Bottlenecks

WSGI (Web Server Gateway Interface) is the traditional standard for Python web applications; each request occupies a thread, and the thread blocks and waits when an I/O operation (such as a database query or network request) occurs.

100%
flowchart LR
    Client1[Client 1] -->|Request| WSGI[WSGI Server]
    Client2[Client 2] -->|Request| WSGI
    Client3[Client 3] -->|Request| WSGI
    WSGI -->|Thread 1| DB1[(Database)]
    WSGI -->|Thread 2| DB1
    WSGI -->|Thread 3 - BLOCKED| DB1
Dimension WSGI ASGI
Connection Model One Request, One Thread Asynchronous Coroutines, Single-Threaded with Multiple Connections
Concurrency Limit Limited by the thread pool (typically 10-100) Virtually unlimited (coroutines are lightweight)
I/O Wait Blocking Thread Non-blocking, switches to another coroutine
WebSocket Not supported Native support
Typical Servers Gunicorn + Flask Uvicorn + FastAPI

(2) The Asynchronous Advantages of ASGI

ASGI (Asynchronous Server Gateway Interface) is an asynchronous extension of WSGI that supports async/await syntax, allowing a single process to handle thousands of concurrent connections.

PYTHON
import asyncio
import time

# WSGI style - blocks thread
def sync_handler():
    time.sleep(1)  # Thread blocked for 1 second
    return "done"

# ASGI style - non-blocking
async def async_handler():
    await asyncio.sleep(1)  # Event loop switches to other tasks
    return "done"

(1) ▶ Example: Comparison of Synchronous vs. Asynchronous Concurrency

PYTHON
import asyncio
import time

async def fetch_price(product_id: int) -> dict:
    # Simulate database I/O latency
    await asyncio.sleep(0.1)
    return {"product_id": product_id, "price": 9.99}

async def main():
    start = time.perf_counter()
    # 100 concurrent requests - async finishes in ~0.1s
    results = await asyncio.gather(*[fetch_price(i) for i in range(100)])
    elapsed = time.perf_counter() - start
    print(f"Async: {len(results)} items in {elapsed:.2f}s")

asyncio.run(main())

Output:

TEXT
Execution Successful

Output:

TEXT
Async: 100 items in 0.10s

4. FastAPI vs. Flask vs. Django DRF

(1) Positioning within the Framework Ecosystem

100%
flowchart LR
    FastAPI[FastAPI] --> Starlette[Starlette ASGI]
    Starlette --> Uvicorn[Uvicorn Server]
    Uvicorn --> ASGI_Protocol[ASGI Protocol]
    FastAPI --> Pydantic[Pydantic V2]
    Flask2[Flask] --> Werkzeug[Werkzeug WSGI]
    Werkzeug --> Gunicorn[Gunicorn]
    Django2[Django DRF] --> Django_Core[Django Core]
Dimension FastAPI Flask Django DRF
Performance (TechEmpower RPS) ~40,000 ~1,200 ~800
Asynchronous Support Native async/await Requires extension Limited support
Automated Documentation OpenAPI Auto-Generation Requires Flask-RESTX Requires drf-spectacular
Type Validation Pydantic Automatic Validation Manual Validation Manual Serializer Definition
Learning Curve Low (Type hints serve as documentation) Low High
Project Scale Small to Medium-Sized API Services Small Services Large Full-Stack Projects

(2) Why FastAPI Is a Better Fit for PriceTracker

PriceTracker Requirements FastAPI Advantages Flask Disadvantages
Millions of queries per second (QPS) High concurrency with asynchronous coroutines Low concurrency with synchronous blocking
Real-time price feeds via WebSocket Native support Not supported
Automatic API Documentation for Bob OpenAPI Auto-Generation Requires Additional Configuration
Request Data Validation Pydantic Automatic Custom Validation Decorator
JWT Authentication Built-in OAuth2 Tools Requires Third-Party Libraries

(1) ▶ Example: Comparison of Three Ways to Write the Same API

PYTHON
# === FastAPI: Type hints = auto validation + docs ===
from fastapi import FastAPI
from pydantic import BaseModel

class Product(BaseModel):
    name: str
    price: float

app = FastAPI()

@app.post("/products")
async def create_product(product: Product):
    return product  # Auto validated, auto documented

Output:

TEXT
# Function defined successfully
PYTHON
# === Flask: Manual validation, no auto docs ===
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/products", methods=["POST"])
def create_product():
    data = request.get_json()
    if not data or "name" not in data or "price" not in data:
        return jsonify({"error": "Invalid data"}), 400
    if not isinstance(data["price"], (int, float)):
        return jsonify({"error": "Price must be number"}), 400
    return jsonify(data)

5. Type Hints Drive Everything

(1) The Threefold Value of Type Hints

FastAPI uses Python type hints to accomplish three things at once: data validation, serialization/deserialization, and OpenAPI documentation generation.

Type Hinting Traditional Frameworks FastAPI
Data Validation Handwritten if/else Pydantic Auto
JSON Serialization Manual json.dumps model_dump() Automatic
API Documentation Hand-written Swagger YAML OpenAPI Auto-Generation
IDE Auto-Complete None Full Type Inference

(1) ▶ Example: Automatic Type Hint Validation

PYTHON
from fastapi import FastAPI, Query
from typing import Optional

app = FastAPI()

@app.get("/prices")
async def search_prices(
    min_price: float = Query(0.0, ge=0, description="Minimum price in USD"),
    max_price: float = Query(999999.0, le=999999, description="Maximum price in USD"),
    category: Optional[str] = Query(None, max_length=50),
):
    return {"min_price": min_price, "max_price": max_price, "category": category}

Output:

TEXT
# Function defined successfully

(2) ▶ Example: Automatically Generated OpenAPI Documentation

PYTHON
# After defining the endpoint above, visit:
# http://localhost:8000/docs  -> Swagger UI
# http://localhost:8000/redoc -> ReDoc
# http://localhost:8000/openapi.json -> Raw OpenAPI schema

Output (excerpt from /openapi.json):

TEXT
{
  "paths": {
    "/prices": {
      "get": {
        "summary": "Search Prices",
        "parameters": [
          {"name": "min_price", "in": "query", "schema": {"type": "number", "minimum": 0.0}}
        ]
      }
    }
  }
}

(2) The Role of Pydantic

Pydantic V2 is a data validation engine for FastAPI; its core has been rewritten in Rust, making it 5 to 50 times faster than V1.

Feature Pydantic V1 Pydantic V2
Core Engine Python Rust (pydantic-core)
Verification Speed Benchmark 5-50x Faster
Validator @validator @field_validator/@model_validator
Configuration class Config model_config = ConfigDict(...)
Serialization .dict() .model_dump()

6. Underlying Architecture: Starlette + Pydantic

(1) FastAPI's Three-Tier Architecture

FastAPI itself is a thin wrapper; its core capabilities come from Starlette (an ASGI framework) and Pydantic (data validation).

Level Component Responsibilities
Application Layer FastAPI Route Registration, Dependency Injection, OpenAPI Generation
ASGI Layer Starlette Middleware, Request/Response Handling, WebSocket
Validation Layer Pydantic Data validation, serialization, and type conversion
Service Layer Uvicorn ASGI Server, Event Loop Management

(1) ▶ Example: Using Starlette Features Directly in FastAPI

PYTHON
from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware
from starlette.responses import JSONResponse

app = FastAPI()

# Starlette middleware works seamlessly with FastAPI
app.add_middleware(CORSMiddleware, allow_origins=["*"])

# Starlette response classes work too
@app.get("/health")
async def health_check():
    return JSONResponse({"status": "healthy"})

Output:

TEXT
# Function defined successfully

(2) ▶ Example: Using Pydantic Models in FastAPI

PYTHON
from fastapi import FastAPI
from pydantic import BaseModel, Field

class PriceCreate(BaseModel):
    product_id: int = Field(gt=0)
    price: float = Field(gt=0, description="Price in USD")
    currency: str = Field(default="USD", max_length=3)

app = FastAPI()

@app.post("/prices")
async def create_price(data: PriceCreate):
    # data is already validated & parsed by Pydantic
    validated = data.model_dump()
    return {"status": "created", "data": validated}

Output:

TEXT
# Function defined successfully

7. An Overview of the PriceTracker Project

(1) What is Alice trying to build?

PriceTracker is a SaaS price tracking API. Its core features include:

Function Module API Endpoint Description
Product Management /products CRUD Millions of Product Records
Price Tracking /prices CRUD Real-Time Price Queries and Notifications
User Authentication /auth/login, /auth/register JWT Dual-Token Authentication
Subscription Plans Free/Pro/Enterprise SaaS Multi-Tenant Permissions
Bulk Import /import/csv Asynchronous Import of 1,000-Row CSV Files
Real-time Push Notifications WebSocket /ws/prices Instant Price Change Alerts
100%
flowchart LR
    Bob[Bob - Frontend] -->|HTTP/WebSocket| API[PriceTracker API]
    Charlie[Charlie - DevOps] -->|Monitor| API
    API -->|Query| DB[(PostgreSQL)]
    API -->|Cache| Redis[(Redis)]
    API -->|Task| Celery[Celery Worker]
    Celery -->|Scrape| External[External Sites]

(1) ▶ Example: PriceTracker—Minimal Working Version

PYTHON
from fastapi import FastAPI
from pydantic import BaseModel, Field
from typing import Optional

app = FastAPI(title="PriceTracker API", version="0.1.0")

class ProductCreate(BaseModel):
    name: str = Field(max_length=200)
    category: str = Field(max_length=100)
    base_price: float = Field(gt=0, description="Base price in USD")

class ProductResponse(BaseModel):
    id: int
    name: str
    category: str
    base_price: float

PRODUCTS_DB: dict[int, dict] = {}
_counter = 0

@app.post("/products", response_model=ProductResponse)
async def create_product(product: ProductCreate):
    global _counter
    _counter += 1
    record = {"id": _counter, **product.model_dump()}
    PRODUCTS_DB[_counter] = record
    return record

@app.get("/products/{product_id}", response_model=ProductResponse)
async def get_product(product_id: int):
    if product_id not in PRODUCTS_DB:
        from fastapi import HTTPException
        raise HTTPException(status_code=404, detail="Product not found")
    return PRODUCTS_DB[product_id]

Output:

TEXT
# Function defined successfully

8. Comprehensive Example

FastAPI's core strength lies in its type-hint-driven automatic validation and documentation generation. The following demonstrates a complete price query endpoint that integrates path parameters, Pydantic models, and response models.

PYTHON
from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI(title="PriceTracker Demo")

class PriceResponse(BaseModel):
    product_id: int = Field(gt=0)
    product_name: str
    price: float = Field(gt=0)
    currency: str = "USD"

PRICES_DB: dict[int, dict] = {
    1: {"product_id": 1, "product_name": "Widget", "price": 9.99},
    2: {"product_id": 2, "product_name": "Gadget", "price": 24.50},
}

@app.get("/products/{product_id}", response_model=PriceResponse)
async def get_price(product_id: int):
    if product_id not in PRICES_DB:
        from fastapi import HTTPException
        raise HTTPException(status_code=404, detail="Product not found")
    return PRICES_DB[product_id]

Output:

TEXT
GET /products/1 → {"product_id":1,"product_name":"Widget","price":9.99,"currency":"USD"}
GET /products/99 → 404 Not Found

❓ FAQ

Q Is FastAPI suitable for large-scale projects?
A Yes, it is. FastAPI's dependency injection, route grouping, and middleware system support modular development for large-scale projects. Companies such as Reddit, Microsoft, and Netflix use it in production.
Q Do I have to use async/await?
A No, you don't have to. FastAPI supports both synchronous and asynchronous view functions. However, async offers better performance in I/O-intensive scenarios (such as database and network requests).
Q What is the relationship between FastAPI and Starlette?
A FastAPI is based on Starlette, which is an ASGI framework. FastAPI builds on Starlette by adding features such as Pydantic validation, dependency injection, and automatic OpenAPI generation.
Q Do I have to use Pydantic V2?
A FastAPI 0.100+ uses Pydantic V2 by default. V2 has a core rewritten in Rust and is 5 to 50 times faster than V1, so we recommend using V2 directly.
Q Can FastAPI replace Django?
A It depends on the use case. FastAPI is an API framework that does not include an ORM, an admin interface, or a template engine. If you only need API services, FastAPI is the better choice; if you need a full-stack CMS, Django is more suitable.
Q Do I need to learn Flask before learning FastAPI?
A No. FastAPI's type-hint-driven approach is completely different from Flask's, so learning FastAPI directly is actually more efficient and helps avoid preconceived notions based on similar concepts.

📖 Summary


📝 Exercises

  1. Basic Exercise (Difficulty: ⭐): Install FastAPI and Uvicorn, create a GET endpoint that returns {"message": "Hello PriceTracker"}, and start it using uvicorn. Hint: pip install fastapi uvicorn
  2. Advanced Problem (Difficulty ⭐⭐): Add the path parameter name to the endpoint, return {"message": "Hello, {name}"}, and visit /docs in your browser to view the auto-generated documentation. Hint: @app.get("/hello/{name}")
  3. Challenge (Difficulty: ⭐⭐⭐): Create a Pydantic model PriceInput that includes product_name: str and price: float (must be > 0), uses a POST endpoint to receive data, and returns the validated result. Hint: Inherit from BaseModel and use Field(gt=0)

---|

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏