Why FastAPI Beats Flask: A Deep Dive into Python Web Frameworks

This article compares Flask and FastAPI, explaining their core differences in speed, developer experience, and standards, and provides detailed code examples for installation, routing, async handling, dependency injection, validation, middleware, testing, deployment, and documentation to help developers decide which framework best fits their Python API projects.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Why FastAPI Beats Flask: A Deep Dive into Python Web Frameworks

FastAPI vs Flask

FastAPI was built with three main goals: speed, developer experience, and open standards. It glues together Starlette, Pydantic, OpenAPI, and JSON Schema, offering ASGI support, automatic data validation, and high performance comparable to Go or Node.js. Flask is a mature WSGI framework with a large ecosystem of extensions and strong community support.

Installation

Flask can be installed with any Python package manager:

pip install flask
# or
poetry add flask
pipenv install flask
conda install flask

FastAPI requires an ASGI server such as Uvicorn:

pip install fastapi uvicorn
# or
poetry add fastapi uvicorn
pipenv install fastapi uvicorn
conda install fastapi uvicorn -c conda-forge

"Hello World" Applications

Flask example:

# flask_code.py
from flask import Flask
app = Flask(__name__)

@app.route("/")
def home():
    return {"Hello": "World"}

if __name__ == "__main__":
    app.run()

FastAPI example:

# fastapi_code.py
import uvicorn
from fastapi import FastAPI
app = FastAPI()

@app.get("/")
def home():
    return {"Hello": "World"}

if __name__ == "__main__":
    uvicorn.run("fastapi_code:app")

HTTP Methods

Flask uses @app.route(..., methods=["GET", "POST"]) to handle multiple methods, while FastAPI provides dedicated decorators such as @app.get, @app.post, @app.delete, and @app.patch.

URL Parameters

Flask:

@app.route("/employee/<int:id>")
def get_employee(id):
    return {"id": id}

FastAPI:

@app.get("/employee/{id}")
def get_employee(id: int):
    return {"id": id}

Query Parameters

Flask extracts query strings via request.args.get:

@app.route("/employee")
def get_employee():
    department = request.args.get("department")
    return {"department": department}

FastAPI declares them as function arguments with type hints:

@app.get("/employee")
def get_employee(department: str):
    return {"department": department}

Templates

Flask uses render_template and looks for files in a templates folder:

@app.route("/")
def home():
    return render_template("index.html")

FastAPI requires Jinja2 and Jinja2Templates to render HTML:

from fastapi import Request
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse

templates = Jinja2Templates(directory="templates")

@app.get("/", response_class=HTMLResponse)
async def home(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})

Static Files

Flask serves static files from a static directory automatically.

FastAPI needs an explicit mount:

from fastapi.staticfiles import StaticFiles
app.mount("/static", StaticFiles(directory="static"), name="static")

Asynchronous Tasks

Since Flask 2.0, async view functions are supported with async/await:

@app.route("/")
async def home():
    result = await some_async_task()
    return result

FastAPI is async‑first; simply declare the function as async def and use await:

@app.get("/")
async def home():
    result = await some_async_task()
    return result

FastAPI also offers BackgroundTasks for fire‑and‑forget work:

from fastapi import BackgroundTasks

@app.post("/upload/{filename}")
async def upload_and_process(filename: str, background_tasks: BackgroundTasks):
    background_tasks.add_task(process_file, filename)
    return {"message": "processing file"}

Dependency Injection

Flask has no built‑in DI; external packages like flask‑injector are required.

FastAPI provides a powerful DI system using Depends:

from fastapi import Depends

def get_db(request: Request):
    return request.app.state._db

@app.get("/data")
def get_data(db: Database = Depends(get_db)):
    return get_all_data(db)

Data Validation

Flask lacks native validation; developers often use Flask‑Pydantic or marshmallow.

FastAPI relies on Pydantic models for request validation and response serialization:

from pydantic import BaseModel

class Request(BaseModel):
    username: str
    password: str

class Response(BaseModel):
    username: str
    email: str

@app.post("/login", response_model=Response)
async def login(req: Request):
    if req.username == "test" and req.password == "test":
        return req
    return {"message": "Authentication Failed"}

Serialization

Flask typically uses jsonify or Flask‑Marshmallow for complex objects.

FastAPI automatically serializes dictionaries and Pydantic models, returning JSON responses.

Middleware

Flask middleware can be implemented as a WSGI wrapper:

class Middleware:
    def __init__(self, app):
        self.app = app
    def __call__(self, environ, start_response):
        start = time.time()
        response = self.app(environ, start_response)
        print(f"request processed in {time.time() - start}s")
        return response

app.wsgi_app = Middleware(app.wsgi_app)

FastAPI provides a decorator‑based approach:

@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.time()
    response = await call_next(request)
    print(f"request processed in {time.time() - start_time}s")
    return response

Modularization

Flask uses Blueprints to split an application into reusable components:

# blueprints/product/views.py
from flask import Blueprint
product = Blueprint("product", __name__)

@product.route("/product1")
def product1():
    ...

# main.py
from blueprints.product.views import product
app.register_blueprint(product)

FastAPI achieves the same with APIRouter:

# routers/product/views.py
from fastapi import APIRouter
product = APIRouter()

@product.get("/product1")
def product1():
    ...

# main.py
from routers.product.views import product
app.include_router(product)

Automatic Documentation

Flask does not generate API docs out of the box; extensions like flask‑swagger or Flask‑RESTX are needed.

FastAPI includes OpenAPI, Swagger UI, and ReDoc automatically, exposing all endpoints and schemas.

FastAPI endpoints list
FastAPI endpoints list

Admin Interfaces

Flask has Flask‑Admin for CRUD UI.

FastAPI alternatives include FastAPI‑Admin and SQLAlchemy‑Admin.

Authentication

Flask relies on third‑party extensions (e.g., Flask‑Login, Flask‑JWT).

FastAPI provides built‑in security utilities via fastapi.security and supports HTTP Basic, OAuth2, JWT, and OpenID Connect.

from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
import secrets

app = FastAPI()
security = HTTPBasic()

def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
    correct_user = secrets.compare_digest(credentials.username, "user")
    correct_pass = secrets.compare_digest(credentials.password, "pass")
    if not (correct_user and correct_pass):
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
    return credentials.username

@app.get("/whoami")
def whoami(username: str = Depends(get_current_username)):
    return {"username": username}

CORS

Flask needs the external Flask‑CORS package:

pip install flask-cors
from flask_cors import CORS
app = Flask(__name__)
CORS(app)

FastAPI includes CORS middleware natively:

from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])

Testing

Flask example using its test client:

def test_hello():
    res = app.test_client().get("/")
    assert res.status_code == 200
    assert res.data == b'{"message":"OK"}
'

FastAPI uses TestClient from fastapi.testclient:

client = TestClient(app)

def test_home():
    res = client.get("/")
    assert res.status_code == 200
    assert res.json() == {"message": "OK"}

Deployment

Flask is typically run behind a production WSGI server such as Gunicorn: gunicorn main:app FastAPI runs with an ASGI server like Uvicorn, optionally managed by Gunicorn workers:

uvicorn main:app
# or with Gunicorn workers
gunicorn -w 3 -k uvicorn.workers.UvicornWorker main:app

Docker

Simple Flask Dockerfile:

FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["gunicorn", "main:app"]

Simple FastAPI Dockerfile:

FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Summary

Flask is a lightweight, extensible micro‑framework with a vast ecosystem, ideal for projects that need flexibility. FastAPI, while newer, offers built‑in async support, automatic validation, and interactive documentation, making it a strong choice for modern, high‑performance APIs, especially when integrating with machine‑learning models.

Official Documentation

FastAPI – https://fastapi.tiangolo.com/

Flask – https://flask.palletsprojects.com/en/2.0.x/

Additional Resources

Porting Flask to FastAPI for ML Model Serving – https://www.pluralsight.com/tech-blog/porting-flask-to-fastapi-for-ml-model-serving/

Why we switched from Flask to FastAPI for production machine learning – https://towardsdatascience.com/why-we-switched-from-flask-to-fastapi-for-production-machine-learning-765aab9b3679

Awesome Flask – https://github.com/mjhea0/awesome-flask

Awesome FastAPI – https://github.com/mjhea0/awesome-fastapi

Author: 宇宙之一粟

Original link: https://juejin.cn/post/7219225476706140218

PythonWeb developmentAPIFlaskComparisonAsyncFastAPI
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.