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 π¦
- Production-Ready Error Handling π‘οΈ
- Docker + Gunicorn + Uvicorn Stack π³β‘
Component | Technology |
---|---|
Framework | FastAPI 0.111+ |
Database | PostgreSQL 14+ |
Cache | Redis 6+ |
ORM | SQLAlchemy 2.0 |
Authentication | JWT (OAuth2 Password Bearer) |
Rate Limiting | Redis-backed Custom Implementation |
Containerization | Docker |
.
βββ app
βΒ Β βββ 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
βΒ Β βββ database.py
βΒ Β βββ settings.py
βββ docs
βΒ Β βββ swagger-screenshot.png
βββ CONTRIBUTORS.txt
βββ Dockerfile
βββ LICENSE
βββ README.md
βββ gunicorn_conf.py
βββ main.py
βββ requirements.txt
βββ run.sh
βββ set_env.sh
βββ tree.txt
7 directories, 28 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 outages
Features:
β
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.8+
- PostgreSQL 14+
- Redis 6+
- Docker (optional)
git clone https://github.com/akhil2308/fastapi-large-app-template.git
cd fastapi-large-app-template
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
- Set environment variables:
source set_env.sh # Sets DB, Redis, and JWT settings
Development:
python main.py
Production:
./run.sh # Starts Gunicorn with Uvicorn workers
Access interactive docs after starting server:
- Swagger UI:
http://localhost:8000/docs
- ReDoc:
http://localhost:8000/redoc
See CONTRIBUTORS.txt for contribution guidelines and code of conduct.
This project is licensed under the MIT License - see LICENSE for details.