Expert guidance for building scalable FastAPI applications following best practices for async operations, error handling, and performance optimization.
Expert guidance for building scalable, high-performance FastAPI applications with modern Python best practices.
This skill provides comprehensive guidance for developing FastAPI applications with focus on:
When developing FastAPI applications, follow these principles and patterns:
1. **Use functional, declarative programming**
- Prefer plain functions over classes where possible
- Use `def` for pure functions and `async def` for asynchronous operations
- Favor iteration and modularization over code duplication
2. **Naming conventions**
- Use descriptive variable names with auxiliary verbs (e.g., `is_active`, `has_permission`)
- Use lowercase with underscores for directories and files (e.g., `routers/user_routes.py`)
- Favor named exports for routes and utility functions
3. **Type safety**
- Use type hints for all function signatures
- Prefer Pydantic models over raw dictionaries for input validation
- Use Pydantic's `BaseModel` for consistent input/output validation and response schemas
4. **File structure**
- Organize files: exported router, sub-routes, utilities, static content, types (models, schemas)
- Use the Receive an Object, Return an Object (RORO) pattern
5. **Prioritize error handling and edge cases**
- Handle errors and edge cases at the beginning of functions
- Use early returns for error conditions to avoid deeply nested if statements
- Place the happy path last in the function for improved readability
- Avoid unnecessary else statements; use the if-return pattern instead
- Use guard clauses to handle preconditions and invalid states early
6. **Error types and responses**
- Use `HTTPException` for expected errors and model them as specific HTTP responses
- Use middleware for handling unexpected errors, logging, and error monitoring
- Implement proper error logging and user-friendly error messages
- Use custom error types or error factories for consistent error handling
7. **Route definitions**
- Use declarative route definitions with clear return type annotations
- Use functional components (plain functions) and Pydantic models
- Rely on FastAPI's dependency injection system for managing state and shared resources
8. **Lifecycle management**
- Minimize `@app.on_event("startup")` and `@app.on_event("shutdown")`
- Prefer lifespan context managers for managing startup and shutdown events
- Use middleware for logging, error monitoring, and performance optimization
9. **Async operations**
- Minimize blocking I/O operations
- Use asynchronous operations for all database calls and external API requests
- Favor asynchronous and non-blocking flows in routes
- Use dedicated async functions for database and external API operations
10. **Caching and optimization**
- Implement caching for static and frequently accessed data using tools like Redis or in-memory stores
- Optimize data serialization and deserialization with Pydantic
- Use lazy loading techniques for large datasets and substantial API responses
- Prioritize API performance metrics (response time, latency, throughput)
11. **Concise conditionals**
- Avoid unnecessary curly braces in conditional statements
- For single-line statements in conditionals, omit curly braces
- Use concise, one-line syntax for simple conditional statements (e.g., `if condition: do_something()`)
12. **Recommended stack**
- FastAPI
- Pydantic v2
- Async database libraries like `asyncpg` or `aiomysql`
- SQLAlchemy 2.0 (if using ORM features)
```python
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
from typing import Optional
app = FastAPI()
class UserCreate(BaseModel):
username: str
email: str
is_active: bool = True
class UserResponse(BaseModel):
id: int
username: str
email: str
@app.post("/users", response_model=UserResponse)
async def create_user(user: UserCreate, db = Depends(get_db)):
# Guard clause - early return
if not user.email:
raise HTTPException(status_code=400, detail="Email is required")
# Guard clause - check existence
existing_user = await db.get_user_by_email(user.email)
if existing_user:
raise HTTPException(status_code=409, detail="User already exists")
# Happy path last
new_user = await db.create_user(user)
return UserResponse(**new_user.dict())
async def get_db():
async with DatabaseSession() as session:
yield session
```
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/fastapi-python-expert-0mjoxq/raw