A production-ready FastAPI template designed for building secure, scalable APIs with modern best practices baked in. This template provides a robust foundation for enterprise-grade applications, featuring essential security measures, performance optimizations, and maintainable architecture patterns out of the box.
- JWT Authentication with refresh tokens π
- Custom Rate Limiting per user/service β±οΈ
- Unified Logging (UVICORN + GUNICORN) π
- Redis Connection Pooling (Async) with fail-open strategy π§
- PostgreSQL Connection Pooling (Async) with health checks π
- Standardized API Responses π¦
- Alembic for Database Migrations ποΈ
- Modern Package Management with
uvβ‘ - Production-Ready Error Handling π‘οΈ
- Docker + Gunicorn + Uvicorn Stack π³β‘
| Component | Technology |
|---|---|
| Framework | FastAPI 0.111+ |
| Database | PostgreSQL 14+ |
| Cache | Redis 6+ |
| ORM | SQLAlchemy 2.0 |
| Migrations | Alembic |
| Authentication | JWT (OAuth2 Password Bearer) |
| Rate Limiting | Redis-backed Custom Implementation |
| Package Manager | uv (fast Python installer) |
| Containerization | Docker |
.
βββ app
βΒ Β βββ alembic
βΒ Β βΒ Β βββ versions
βΒ Β βΒ Β βββ README
βΒ Β βΒ Β βββ env.py
βΒ Β βΒ Β βββ script.py.mako
βΒ Β βββ core
βΒ Β βΒ Β βββ __init__.py
βΒ Β βΒ Β βββ database.py
βΒ Β βΒ Β βββ logging_config.py
βΒ Β βΒ Β βββ settings.py
βΒ Β βββ health
βΒ Β βΒ Β βββ health_router.py
βΒ Β βββ todo
βΒ Β βΒ Β βββ todo_crud.py
βΒ Β βΒ Β βββ todo_model.py
βΒ Β βΒ Β βββ todo_router.py
βΒ Β βΒ Β βββ todo_schema.py
βΒ Β βΒ Β βββ todo_service.py
βΒ Β βββ user
βΒ Β βΒ Β βββ user_auth.py
βΒ Β βΒ Β βββ user_crud.py
βΒ Β βΒ Β βββ user_model.py
βΒ Β βΒ Β βββ user_router.py
βΒ Β βΒ Β βββ user_schema.py
βΒ Β βΒ Β βββ user_service.py
βΒ Β βββ utils
βΒ Β βΒ Β βββ auth_dependency.py
βΒ Β βΒ Β βββ helper.py
βΒ Β βΒ Β βββ rate_limiter.py
βΒ Β βββ alembic.ini
βΒ Β βββ main.py
βββ docs
βΒ Β βββ swagger-screenshot.png
βββ tests
βΒ Β βββ __init__.py
βΒ Β βββ test_health.py
βββ CONTRIBUTORS.txt
βββ Dockerfile
βββ LICENSE
βββ README.md
βββ gunicorn_config.py
βββ pyproject.toml
βββ run.sh
βββ tree.txt
11 directories, 35 files
PostgreSQL (SQLAlchemy 2.0 + asyncpg):
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
# Async PostgreSQL connection pool
engine = create_async_engine(
"postgresql+asyncpg://user:pass@host:port/dbname",
pool_size=20, # Persistent connection pool size
max_overflow=10, # Temporary connections beyond pool_size
pool_recycle=300, # Recycle connections every 300s
pool_pre_ping=True, # Validate connections before use
future=True # Enable SQLAlchemy 2.0 behavior
)
# Async session factory configuration
AsyncSessionLocal = async_sessionmaker(
bind=engine,
expire_on_commit=False, # Prevent attribute expiration on commit
autoflush=False, # Manual flush control
class_=AsyncSession # Use SQLAlchemy's async session class
)Key Features:
- π Full Async Support: Non-blocking database operations via asyncpg
- π Connection Recycling: Prevents stale connections in long-running applications
- π©Ί Connection Validation: Pre-ping checks verify connection health
- π Optimized Pooling: Balances memory usage and concurrent requests
- β‘ SQLAlchemy 2.0: Future-proof API with explicit transaction control
Redis Connection Pool:
redis = await Redis(
host="redis.prod.internal",
port=6379,
db=0,
password="securepassword",
socket_connect_timeout=5, # 5s connection timeout
socket_keepalive=True, # Maintain TCP keepalive
retry_on_timeout=True, # Auto-retry failed operations
max_connections=100, # Max pool size
health_check_interval=30 # Validate connections every 30s
)- Enterprise Features: TLS support, cluster mode ready
- Resiliency: Automatic retries and health checks
Protected Todo Creation:
@router.post("/")
async def create_todo(
body: TodoCreate,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db)
):
"""
Implements:
- JWT Authentication
- User-based Rate Limiting
- Structured Error Handling
- Audit Logging
"""
try:
# Rate limit check
await user_rate_limiter(current_user.user_id, "todo_write")
# Business logic
data = await create_todo_service(current_user.user_id, body, db)
# Standardized success response
return {
"status": "success",
"message": "Todo created",
"data": data
}
except HTTPException as e:
# Preserve existing HTTP exceptions
raise
except Exception as e:
# Log full error context
logger.error(f"Todo creation failed: {str(e)}", exc_info=True)
# Return standardized error format
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal server error"
)Implementation:
async def user_rate_limiter(
user_id: str,
service: str,
times: int = 5,
seconds: int = 60
):
"""
Redis-backed rate limiter using LUA scripts for atomic operations
"""
key = f"rl:user:{user_id}:{service}"
try:
pexpire = await FastAPILimiter.redis.evalsha(
FastAPILimiter.lua_sha, 1,
key,
str(times),
str(seconds * 1000) # Convert to milliseconds
)
if pexpire != 0:
raise HTTPException(
status_code=429,
detail=f"Try again in {ceil(pexpire/1000)} seconds"
)
except Exception as e:
logger.error(f"Rate limit check failed: {str(e)}")
# Fail-open during Redis outagesFeatures: β User+service specific limits β Atomic Redis operations via LUA scripts β Fail-open circuit breaker pattern β Millisecond precision timeouts β Automatic retry-after calculation
Configuration:
logging_config = {
"version": 1,
"formatters": {
"standard": {
"format": "[{asctime}] [{process}] [{levelname}] {module}.{funcName}:{lineno} - {message}",
"datefmt": "%Y-%m-%d %H:%M:%S %z",
"style": "{"
}
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"formatter": "standard",
"stream": "ext://sys.stdout"
}
},
"loggers": {
"": {"level": "DEBUG", "handlers": ["console"], "propagate": False},
"uvicorn": {"level": "INFO", "propagate": False},
"uvicorn.access": {"level": "INFO", "propagate": False},
"uvicorn.error": {"level": "INFO", "propagate": False}
}
}Log Example:
[2024-05-20 14:30:45 +0000] [1234] [INFO] todo.routers.create_todo:52 - Created todo ID:42
Features: π Consistent timestamp with timezone π Process ID tracking π Module/function/line number context π Uvicorn log unification π Production-ready INFO level defaults
Success Response:
{
"status": "success",
"message": "Todo created successfully",
"data": {
"id": 42,
"task": "Implement rate limiting"
}
}Error Response:
{
"status": "error",
"message": "Validation Failed",
"errors": [
{
"field": "task",
"message": "Field required"
}
]
}Implementation:
@app.exception_handler(RequestValidationError)
async def validation_handler(request: Request, exc: RequestValidationError):
return JSONResponse(
status_code=422,
content={
"status": "error",
"code": 422,
"message": "Validation Failed",
"errors": exc.errors()
}
)
@app.exception_handler(HTTPException)
async def http_handler(request: Request, exc: HTTPException):
return JSONResponse(
status_code=exc.status_code,
content={
"status": "error",
"code": exc.status_code,
"message": exc.detail,
"errors": getattr(exc, "errors", None)
}
)Features: β RFC-compliant error formats β Automatic validation error parsing β Consistent error code mapping β Detailed error context preservation
- Python 3.11+
- PostgreSQL 14+
- Redis 6+
- Docker (optional)
git clone https://github.com/akhil2308/fastapi-large-app-template.git
cd fastapi-large-app-template
# Install uv (if not already installed)
pip install uv
# Sync dependencies and create virtual environment
# This installs all packages defined in pyproject.toml
uv sync --all-extras
# Install Git Hooks
# This ensures code quality checks run automatically on commit
uv run pre-commit installcp .env.example .env
# Fill in DB, Redis, JWT, and other valuesGenerate new migration:
uv run alembic -c app/alembic.ini revision --autogenerate -m "message"Apply migrations:
uv run alembic -c app/alembic.ini upgrade headDevelopment:
uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000Production:
./run.sh # Starts Gunicorn with Uvicorn workersThis project enforces code quality using Ruff (linter/formatter) and Mypy (static type checker).
1. Linting & Formatting (Ruff)
# See what code Ruff wants to fix (Dry Run)
uv run ruff check .
# Actually fix the code (Auto-formatting & Import sorting)
uv run ruff check . --fix
uv run ruff format .2. Static Type Checking (Mypy)
# Check for type errors
uv run mypy .Note: π A pre-commit hook is configured. When you attempt to
git commit, these checks will automatically run to ensure no bad code is pushed to the repository.
---
## API Documentation π
Access interactive docs after starting server:
- **Swagger UI:** `http://localhost:8000/docs`
- **ReDoc:** `http://localhost:8000/redoc`
- **OpenAPI:** `http://localhost:8000/openapi.json`
## Contributing
See [CONTRIBUTORS.txt](CONTRIBUTORS.txt) for contribution guidelines and code of conduct.
## License
This project is licensed under the MIT License - see [LICENSE](LICENSE) for details.