FastAPI Development Guide
Build modern, fast Python APIs from hello world to production-ready applications.
Before Implementation
Gather context to ensure successful implementation:
Source Gather
Codebase Existing project structure, database setup, auth patterns, dependencies
Conversation User's specific API requirements, preferred database, deployment target
Skill References Relevant patterns from references/ directory
User Guidelines Project-specific conventions, naming standards
Clarifications
Required (ask if not clear)
-
Project type? Simple API / Production application / Microservice
-
Database? PostgreSQL / SQLite / None / Other
-
Authentication needed? JWT / API Key / OAuth2 / None
Optional (ask if relevant)
-
Deployment target? Docker / Cloud (Railway/Render/Fly.io) / Local only
-
Testing approach? TDD / Post-implementation / None
Official Documentation
Resource URL Use For
FastAPI Docs https://fastapi.tiangolo.com Official reference, tutorials
Pydantic Docs https://docs.pydantic.dev Model validation, settings
SQLAlchemy Docs https://docs.sqlalchemy.org Database ORM patterns
Uvicorn https://www.uvicorn.org ASGI server configuration
Alembic https://alembic.sqlalchemy.org Database migrations
Version Note: This skill follows FastAPI 0.100+ and Pydantic v2 patterns. For older versions, check official migration guides.
Quick Start
uv init my-api && cd my-api uv add "fastapi[standard]"
from fastapi import FastAPI
app = FastAPI()
@app.get("/") async def root(): return {"message": "Hello World"}
uv run fastapi dev main.py
Access at http://127.0.0.1:8000 | Docs at /docs | ReDoc at /redoc
Project Structure
Simple projects:
project/ ├── main.py ├── requirements.txt └── .env
Production projects:
project/ ├── app/ │ ├── init.py │ ├── main.py # FastAPI app instance │ ├── config.py # Settings/configuration │ ├── dependencies.py # Shared dependencies │ ├── models/ # SQLAlchemy models │ ├── schemas/ # Pydantic schemas │ ├── routers/ # API route modules │ ├── services/ # Business logic │ └── utils/ # Helper functions ├── tests/ ├── alembic/ # DB migrations ├── requirements.txt ├── .env └── Dockerfile
Core Concepts
Path Operations
@app.get("/items/{item_id}") # Read @app.post("/items/") # Create @app.put("/items/{item_id}") # Update (full) @app.patch("/items/{item_id}") # Update (partial) @app.delete("/items/{item_id}") # Delete
Parameters
from fastapi import FastAPI, Query, Path, Body
@app.get("/items/{item_id}") async def read_item( item_id: int = Path(..., ge=1), # Path param, required, >= 1 q: str | None = Query(None, max_length=50), # Query param, optional skip: int = Query(0, ge=0), # Query param with default ): return {"item_id": item_id, "q": q, "skip": skip}
Request/Response Models
from pydantic import BaseModel, Field, EmailStr
class UserCreate(BaseModel): email: EmailStr password: str = Field(..., min_length=8) name: str
class UserResponse(BaseModel): id: int email: EmailStr name: str
model_config = {"from_attributes": True}
@app.post("/users/", response_model=UserResponse) async def create_user(user: UserCreate): # Create user in DB... return user
Dependency Injection
from fastapi import Depends
async def get_db(): db = SessionLocal() try: yield db finally: db.close()
async def get_current_user(token: str = Depends(oauth2_scheme)): user = decode_token(token) if not user: raise HTTPException(401, "Invalid token") return user
@app.get("/users/me") async def read_users_me(user: User = Depends(get_current_user)): return user
Error Handling
from fastapi import HTTPException from fastapi.responses import JSONResponse
Simple exception
raise HTTPException(status_code=404, detail="Item not found")
Custom exception handler
class ItemNotFound(Exception): def init(self, item_id: int): self.item_id = item_id
@app.exception_handler(ItemNotFound) async def item_not_found_handler(request, exc): return JSONResponse( status_code=404, content={"message": f"Item {exc.item_id} not found"} )
Workflow Selection
Starting a new project? → See references/basics.md
Need data validation/schemas? → See references/models-validation.md
Connecting a database? → See references/database.md
Adding authentication? → See references/authentication.md
Need WebSockets, background tasks, or middleware? → See references/advanced.md
Writing tests? → See references/testing.md (includes TDD workflow)
Deploying to production? → See references/deployment.md
Searching Large References
For specific patterns in reference files, use grep:
Authentication patterns
grep -n "JWT|OAuth2|token|password" references/authentication.md
Database patterns
grep -n "async|session|CRUD|relationship" references/database.md
Testing patterns
grep -n "fixture|mock|async_client" references/testing.md
Deployment patterns
grep -n "Docker|gunicorn|nginx" references/deployment.md
Common Patterns
Router Organization
app/routers/users.py
from fastapi import APIRouter
router = APIRouter(prefix="/users", tags=["users"])
@router.get("/") async def list_users(): return []
@router.get("/{user_id}") async def get_user(user_id: int): return {"id": user_id}
app/main.py
from fastapi import FastAPI from app.routers import users, items
app = FastAPI() app.include_router(users.router) app.include_router(items.router)
Background Tasks
from fastapi import BackgroundTasks
def send_email(email: str, message: str): # Send email logic... pass
@app.post("/send-notification/") async def send_notification( email: str, background_tasks: BackgroundTasks ): background_tasks.add_task(send_email, email, "Welcome!") return {"message": "Notification sent in background"}
File Upload
from fastapi import UploadFile, File
@app.post("/upload/") async def upload_file(file: UploadFile = File(...)): contents = await file.read() return { "filename": file.filename, "size": len(contents), "content_type": file.content_type }
CORS
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:3000"], allow_credentials=True, allow_methods=[""], allow_headers=[""], )
Essential Dependencies
Core
uv add "fastapi[standard]"
Database
uv add sqlalchemy asyncpg alembic # PostgreSQL async uv add sqlalchemy aiosqlite # SQLite async
Authentication
uv add "python-jose[cryptography]" "passlib[bcrypt]"
Validation
uv add "pydantic[email]"
Testing
uv add pytest pytest-asyncio httpx --dev
Common Mistakes
Mistake Why It's Wrong Fix
allow_origins=["*"] in production Security risk, allows any origin Use specific domains
Hardcoding SECRET_KEY
Exposed in version control Use environment variables
Missing response_model
May leak sensitive fields (password) Always filter responses
Forgetting await in async DB Coroutine never executes Add await to async calls
No input validation SQL injection, invalid data Use Pydantic models
Sync operations in async routes Blocks event loop Use async libraries
Quick Reference
Need Solution
Run dev server uv run fastapi dev main.py
Run prod server uv run fastapi run main.py or uv run uvicorn app.main:app
Path parameter @app.get("/items/{id}")
Query parameter def func(q: str = None)
Request body def func(item: ItemModel)
Require auth Depends(get_current_user)
Database session Depends(get_db)
Return specific model response_model=UserResponse
Background work BackgroundTasks
WebSocket @app.websocket("/ws")
Before Delivery Checklist
Code Quality
-
All endpoints have appropriate HTTP status codes (201 for create, 204 for delete)
-
Sensitive data filtered via response_model (no passwords in responses)
-
Input validation using Pydantic models
-
Error handling with proper HTTPException messages
Security
-
SECRET_KEY from environment variable
-
CORS configured with specific origins (not * )
-
Authentication on protected routes
-
No hardcoded credentials
Testing
-
Tests written for all endpoints
-
Error cases covered (404, 401, 422)
-
Tests pass: uv run pytest
Documentation
-
OpenAPI docs accessible at /docs
-
Endpoints have descriptive tags and summaries