█
LastWrite
  • > Curriculum
  • > Pricing
  • > For Educators
  • > About
  • > Contact
Log InGet Started

Questions, concerns, bug reports, or suggestions? We read every message, write to us at [email protected].

More ways to reach us →
LastWrite

Structured computer science lessons for aspiring developers and security professionals.

[email protected]

(201) 785-7951

Mon–Fri, 9 AM–5 PM EST

Learn

  • Curriculum
  • Pricing

Company

  • About
  • For Educators & Schools
  • Contact Us

Legal

  • Terms of Service
  • Privacy Policy
© 2026 LastWrite. All rights reserved.
Curriculum/Programming Languages/Python (Professional)/Python for Backend: FastAPI
55 minIntermediate

Python for Backend: FastAPI

After this lesson, you will be able to: Build a typed, async Python backend with FastAPI: validate requests with Pydantic, talk to PostgreSQL through SQLAlchemy, manage schema changes with Alembic, and run it in Docker.

Python's dominant modern web framework is FastAPI: async, type-driven, and fast. It uses the type hints you already learned to validate input, serialize output, and generate interactive API docs for free. This lesson is the backend stack employers actually ask for, FastAPI + Pydantic + SQLAlchemy + Alembic, and it turns your Python knowledge into a deployable service.

Prerequisites:Async Python

Why FastAPI (and not Flask or Django) for new APIs

Flask is minimal but unopinionated and sync-first; Django is batteries-included but heavy and built around server-rendered pages. FastAPI hits the modern sweet spot for APIs: it is async-native (great for I/O-bound workloads), it uses Python type hints to validate and document automatically, and it is one of the fastest Python frameworks. The headline feature: declare a Pydantic model for your request body and FastAPI validates incoming JSON against it, returns a clear 422 on bad input, and publishes interactive Swagger docs at /docs with zero extra code. Django still wins when you want an admin panel and tight ORM integration; for a typed JSON API in 2025, FastAPI is the default.

A FastAPI endpoint with Pydantic validation

The type hints are the validation. FastAPI reads them at runtime.

python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, EmailStr, Field
app = FastAPI()
# Pydantic model = request schema + validation + docs, all from types
class CreateUser(BaseModel):
email: EmailStr
name: str = Field(min_length=1, max_length=100)
age: int = Field(ge=0, le=150)
class UserOut(BaseModel):
id: int
email: EmailStr
name: str
@app.post("/users", response_model=UserOut, status_code=201)
async def create_user(payload: CreateUser):
# payload is already validated; bad JSON never reaches here (FastAPI returns 422)
user = await db_create_user(payload) # your DB call
return user
@app.get("/users/{user_id}", response_model=UserOut)
async def get_user(user_id: int):
user = await db_get_user(user_id)
if user is None:
raise HTTPException(status_code=404, detail="User not found")
return user
# Run: uvicorn main:app --reload -> interactive docs at http://localhost:8000/docs

SQLAlchemy for the database, Alembic for migrations

SQLAlchemy is the standard Python ORM; Alembic versions your schema the way Prisma Migrate does for Node.

python
# models.py: SQLAlchemy 2.0 typed models
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase): ...
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
email: Mapped[str] = mapped_column(unique=True)
name: Mapped[str]
# Alembic: version-controlled schema changes
# alembic init alembic # one-time setup
# alembic revision --autogenerate -m "create users" # diff models -> migration
# alembic upgrade head # apply to the database
# alembic downgrade -1 # roll back one revision
# Never edit a shipped table by hand; generate a migration so every
# environment applies the same change in the same order.

💡 Pydantic vs SQLAlchemy models: keep them separate

A common beginner tangle: trying to use one class for both the API schema and the database table. Keep them distinct. SQLAlchemy models describe the database (columns, relationships, constraints). Pydantic models describe the API boundary (what clients send and receive). The endpoint validates input with a Pydantic model, maps it to a SQLAlchemy model to persist, then returns a Pydantic `response_model` so you never accidentally leak a column (like a password hash) to the client. This separation is exactly the API-design discipline from the System Design and REST API lessons.

Running it for real: uvicorn, Docker, deploy

FastAPI runs under an ASGI server, usually uvicorn (or gunicorn with uvicorn workers in production). For deployment you containerize it: a slim Python base image, install dependencies, copy code, run uvicorn, and run as a non-root user (the Docker security lesson applies directly). Push the image and deploy to Railway or Render (both have free tiers and detect a Dockerfile automatically), or to any container host. Put secrets (the database URL) in environment variables, never in the image. The result is a live, documented API at a public URL, which is exactly the passion project this subtrack builds toward.

Common mistakes only experienced engineers catch

Defining sync endpoints that call blocking I/O on the async event loop, which stalls the whole server. Use async DB drivers (asyncpg via SQLAlchemy async) or run blocking work in a threadpool. Reusing a SQLAlchemy model as the API response and leaking columns (password hashes, internal flags). Return a Pydantic response_model. Editing the database by hand instead of generating an Alembic migration, so environments drift. Skipping `response_model`, losing both output validation and accurate docs. Hardcoding the database URL instead of reading it from an environment variable, then committing the credential.

Quick Check

Why declare a Pydantic model for a FastAPI request body?

Pick the most complete answer.

Sign in and purchase access to unlock this lesson.

Sign in to purchase
←Regular Expressions
Back to Python (Professional)
Passion Project: Python CLI Tool→