FastAPI Code Review Rules
Security (Critical)
- Input Validation: Apply strict type, length, and format checks to all user-supplied input. Sanitize inputs using trusted libraries before any rendering or database operation
- Template Variable Safety: Never render unvalidated template variables (
{{ ... }}), and always declare variable sources. Avoid HTML comments (<!-- -->) as they may expose sensitive info or facilitate injection attacks - Comment Hygiene: Never use HTML comments in production code to store data or instructions
- Use
OAuth2PasswordBeareror similar for auth - Rate limit sensitive endpoints
- Never log sensitive data (passwords, tokens)
- Implement CORS properly with
CORSMiddleware - Use CSRF protection for cookie-based auth
- Validate content types and sanitize HTML to prevent XSS
- Use security headers (HSTS, CSP, X-Frame-Options)
- Always validate user input in path operations and request bodies
Endpoint Design (Essential)
- Use appropriate HTTP methods (GET for reads, POST for creates, etc.)
- Return appropriate status codes (201 for create, 204 for delete, etc.)
- Use path parameters for resource identifiers, query params for filtering
- Group related endpoints with
APIRouterand tags - Document endpoints with clear docstrings
Endpoint Design (Advanced)
- Use OpenAPI metadata (summary, description, response descriptions)
- Provide detailed response model documentation
- Implement API versioning (URL prefix recommended)
- Mark deprecated endpoints with
deprecated=True
Pydantic Models (Essential)
- Use Pydantic models for request body validation (not raw dicts)
- Define explicit response models with
response_modelparameter - Use
Field()for validation constraints (min/max, regex, etc.) - Separate input models from output models (Create vs Response)
- Use type annotations for all endpoint arguments and return types
- Return only JSON-serializable results
- Use
model_configfor Pydantic v2 configuration
Dependency Injection
- Use
Depends()for shared logic (auth, db sessions, etc.) - Database sessions should be dependencies, not global
- Close resources properly (use context managers or finally)
Async (Essential)
- Use
async deffor I/O-bound endpoints - Don't mix sync and async database calls
- Use
asyncio.gather()for parallel async operations - Avoid blocking calls in async functions (use
run_in_executor)
Async (Advanced)
- Use async context managers (
async with) for managing async resources (DB sessions, HTTP clients) - Use
BackgroundTasksfor work that should outlive the response - Use startup/shutdown events (
@app.on_event("startup"/"shutdown")) to initialize/cleanup shared async resources - Apply concurrency limits with
asyncio.Semaphorewhen calling external services - For streaming responses or WebSockets, implement backpressure-aware designs
- For more patterns, see FastAPI Async Documentation
Error Handling
- Use
HTTPExceptionfor expected errors with proper status codes - Create custom exception handlers for domain exceptions
- Don't expose internal error details to clients
- Log errors with context (request ID, user, etc.)
Project Structure
- Organize by feature or layer (routers, models, services, dependencies)
- Keep routers thin - business logic in services
- Separate Pydantic models from database models
- Use a
dependenciesmodule for reusable dependencies - Create
config.pyfor settings management