13 KiB
Python Backend Technology Stack Recommendations
This document provides curated recommendations for common technology choices in Python backend development.
Web Frameworks
FastAPI (Recommended for Modern APIs)
Best for: Microservices, RESTful APIs, async-first applications
Pros:
- Automatic OpenAPI/Swagger documentation
- Built-in request/response validation with Pydantic
- High performance (comparable to Node.js/Go)
- Native async/await support
- Type hints and IDE support
- Modern Python features
Cons:
- Smaller ecosystem compared to Django
- Less built-in features (need to integrate more libraries)
- Newer framework (less mature)
When to use:
- Building new REST or GraphQL APIs
- High-performance requirements
- Microservices architecture
- Team comfortable with modern Python
Django (Recommended for Full-Featured Applications)
Best for: Monolithic applications, admin-heavy apps, rapid development
Pros:
- Batteries-included (ORM, admin, auth, forms, etc.)
- Massive ecosystem and community
- Battle-tested and mature
- Excellent documentation
- Built-in admin interface
- Strong security defaults
Cons:
- Heavier framework
- Less suitable for microservices
- Async support is newer and limited
- More opinionated structure
When to use:
- Building full-featured web applications
- Need admin interface out of the box
- Rapid prototyping
- Team prefers convention over configuration
Flask (Recommended for Simple APIs)
Best for: Small to medium applications, prototypes, simple APIs
Pros:
- Lightweight and flexible
- Easy to learn
- Large ecosystem of extensions
- Minimal boilerplate
- Great for prototypes
Cons:
- Requires more setup for production
- No built-in async support (requires extensions)
- Need to choose and integrate many components
- Less structure by default
When to use:
- Small to medium applications
- Prototypes and MVPs
- Learning Python web development
- Need maximum flexibility
Async Frameworks
Comparison
| Feature | FastAPI | Starlette | Quart | aiohttp |
|---|---|---|---|---|
| Performance | Excellent | Excellent | Good | Excellent |
| Documentation | Excellent | Good | Good | Good |
| Ease of Use | Excellent | Good | Excellent | Moderate |
| Community | Growing | Moderate | Small | Moderate |
| Best For | APIs | Custom apps | Flask users | Low-level control |
Database Solutions
PostgreSQL (Recommended for Most Cases)
Best for: Production applications requiring ACID compliance
Pros:
- ACID compliant
- Rich feature set (JSONB, full-text search, etc.)
- Excellent performance
- Strong community
- Great for complex queries
Libraries:
asyncpg- Fastest async driverpsycopg2- Traditional sync driverpsycopg3- Modern sync/async driver
MySQL/MariaDB
Best for: Applications with heavy read operations
Pros:
- Fast read performance
- Wide hosting support
- Good replication
- Mature ecosystem
Libraries:
aiomysql- Async drivermysqlclient- Sync driver (fastest)PyMySQL- Pure Python sync driver
MongoDB
Best for: Flexible schema, document-oriented data
Pros:
- Schema flexibility
- Horizontal scaling
- Good for rapid development
- Rich query language
Libraries:
motor- Async driver (recommended)pymongo- Sync driver
Redis
Best for: Caching, sessions, real-time features
Pros:
- Extremely fast
- Rich data structures
- Pub/sub support
- Good for caching and sessions
Libraries:
redis-py- Official client with async supportaioredis- Async-first client (now merged into redis-py)
ORM Solutions
SQLAlchemy (Recommended)
Best for: Complex queries, database agnostic code
Pros:
- Most mature Python ORM
- Powerful query API
- Database agnostic
- Great documentation
- Good async support (2.0+)
Cons:
- Steeper learning curve
- More verbose than alternatives
# Async SQLAlchemy 2.0
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import declarative_base, sessionmaker
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db")
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
Tortoise ORM
Best for: Async-first applications, Django-like syntax
Pros:
- Built for async from the ground up
- Django-like API
- Easy to learn
- Good documentation
Cons:
- Smaller community
- Fewer features than SQLAlchemy
- Limited database support
from tortoise import fields, models
from tortoise.contrib.fastapi import register_tortoise
class User(models.Model):
id = fields.IntField(pk=True)
email = fields.CharField(max_length=255, unique=True)
name = fields.CharField(max_length=255)
Django ORM
Best for: Django projects
Pros:
- Integrated with Django
- Simple and intuitive
- Excellent documentation
- Good async support (3.1+)
Cons:
- Tied to Django
- Less powerful than SQLAlchemy for complex queries
API Documentation
OpenAPI/Swagger (FastAPI Built-in)
Recommended for: REST APIs
Libraries:
- FastAPI includes automatic generation
flasggerfor Flaskdrf-spectacularfor Django REST Framework
GraphQL
Strawberry (Recommended for FastAPI)
import strawberry
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter
@strawberry.type
class Query:
@strawberry.field
def hello(self) -> str:
return "Hello World"
schema = strawberry.Schema(query=Query)
graphql_app = GraphQLRouter(schema)
Other Options:
Graphene- Mature, works with DjangoAriadne- Schema-first approach
Authentication & Authorization
JWT Authentication
Libraries:
python-jose[cryptography]- Recommended for JWTPyJWT- Lightweight alternative
from jose import JWTError, jwt
from datetime import datetime, timedelta
def create_access_token(data: dict):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=15)
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
OAuth2
Libraries:
authlib- Comprehensive OAuth client/serverpython-social-auth- Social authentication
Password Hashing
Libraries:
passlib[bcrypt]- Recommendedargon2-cffi- Most secure (memory-hard)
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str) -> str:
return pwd_context.hash(password)
def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password)
Task Queues
Celery (Recommended for Most Cases)
Best for: Complex workflows, scheduled tasks
Pros:
- Mature and battle-tested
- Rich feature set
- Good monitoring tools
- Supports multiple brokers
Cons:
- Complex configuration
- Heavy dependency
from celery import Celery
app = Celery('tasks', broker='redis://localhost:6379/0')
@app.task
def process_data(data):
# Long-running task
pass
RQ (Redis Queue)
Best for: Simple job queues
Pros:
- Simple to use
- Lightweight
- Good for simple tasks
Cons:
- Less features than Celery
- Only works with Redis
Dramatiq
Best for: Alternatives to Celery
Pros:
- Simpler than Celery
- Good performance
- Type-safe
Cons:
- Smaller community
Validation & Serialization
Pydantic (Recommended)
Best for: Data validation, settings management
from pydantic import BaseModel, EmailStr, validator
class User(BaseModel):
id: int
email: EmailStr
name: str
age: int
@validator('age')
def validate_age(cls, v):
if v < 0:
raise ValueError('Age must be positive')
return v
Marshmallow
Best for: Flask applications, complex serialization
HTTP Clients
httpx (Recommended)
Best for: Modern async/sync HTTP client
import httpx
async with httpx.AsyncClient() as client:
response = await client.get('https://api.example.com')
aiohttp
Best for: Async-only applications
requests
Best for: Sync-only applications (legacy)
Testing
pytest (Recommended)
Essential plugins:
pytest-asyncio- Async test supportpytest-cov- Coverage reportingpytest-mock- Mocking utilitiespytest-xdist- Parallel testing
import pytest
from httpx import AsyncClient
@pytest.mark.asyncio
async def test_create_user(client: AsyncClient):
response = await client.post("/users", json={"email": "test@example.com"})
assert response.status_code == 201
Other Tools
coverage- Code coveragefaker- Test data generationfactory_boy- Test fixturesresponses- Mock HTTP requests
Observability
Logging
Recommended:
structlog- Structured loggingpython-json-logger- JSON logging- Built-in
loggingmodule
Metrics
Recommended:
prometheus-client- Prometheus metricsstatsd- StatsD client
Tracing
Recommended:
opentelemetry-api+opentelemetry-sdk- OpenTelemetryddtrace- DataDog APMsentry-sdk- Error tracking
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("process_data"):
# Your code here
pass
Security
Security Headers
from fastapi.middleware.trustedhost import TrustedHostMiddleware
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(TrustedHostMiddleware, allowed_hosts=["example.com"])
app.add_middleware(
CORSMiddleware,
allow_origins=["https://example.com"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
Security Libraries
bandit- Security lintingsafety- Dependency vulnerability scanningpython-dotenv- Environment variable management
Development Tools
Code Quality
ruff- Fast linter and formatter (recommended)black- Code formatterisort- Import sortingmypy- Static type checkingpylint- Comprehensive linting
Dependency Management
poetry- Recommended for modern projectspdm- Fast alternative to poetrypip-tools- Minimal approach (pip-compile)
Pre-commit Hooks
# .pre-commit-config.yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.6
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.7.1
hooks:
- id: mypy
Deployment
ASGI Servers
uvicorn- Recommended for FastAPIhypercorn- HTTP/2 supportdaphne- Django channels
WSGI Servers
gunicorn- Recommended for Django/Flaskuwsgi- Alternative option
Production Setup
# Uvicorn with Gunicorn (recommended for production)
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker
Configuration Management
Pydantic Settings (Recommended)
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
database_url: str
redis_url: str
secret_key: str
class Config:
env_file = ".env"
python-decouple
Simple alternative for basic configuration
Message Brokers
RabbitMQ
Best for: Complex routing, guaranteed delivery
Libraries:
aio-pika- Async AMQP client
Apache Kafka
Best for: Event streaming, high throughput
Libraries:
aiokafka- Async Kafka clientconfluent-kafka- High-performance client
Redis Pub/Sub
Best for: Simple pub/sub, low latency
Libraries:
redis-pywith pub/sub support
Recommended Stack Combinations
Modern Microservices Stack
- Framework: FastAPI
- Database: PostgreSQL (asyncpg)
- ORM: SQLAlchemy 2.0 (async)
- Cache: Redis
- Task Queue: Celery or Dramatiq
- Validation: Pydantic
- Testing: pytest + httpx
- Observability: OpenTelemetry + Sentry
- Deployment: Uvicorn + Docker + Kubernetes
Traditional Monolith Stack
- Framework: Django
- Database: PostgreSQL (psycopg2)
- ORM: Django ORM
- Cache: Redis
- Task Queue: Celery
- API: Django REST Framework
- Testing: pytest-django
- Deployment: Gunicorn + Docker
Lightweight API Stack
- Framework: Flask or FastAPI
- Database: PostgreSQL or MongoDB
- ORM: SQLAlchemy or Motor
- Testing: pytest
- Deployment: Uvicorn or Gunicorn
Version Recommendations (as of 2025)
# pyproject.toml
[tool.poetry.dependencies]
python = "^3.11" # Python 3.11+ recommended for performance
fastapi = "^0.110.0"
uvicorn = {extras = ["standard"], version = "^0.27.0"}
sqlalchemy = "^2.0.25"
asyncpg = "^0.29.0"
pydantic = "^2.5.0"
pydantic-settings = "^2.1.0"
redis = "^5.0.1"
celery = "^5.3.4"
python-jose = {extras = ["cryptography"], version = "^3.3.0"}
passlib = {extras = ["bcrypt"], version = "^1.7.4"}
httpx = "^0.26.0"
structlog = "^24.1.0"
opentelemetry-api = "^1.22.0"
opentelemetry-sdk = "^1.22.0"
sentry-sdk = "^1.39.0"
[tool.poetry.group.dev.dependencies]
pytest = "^7.4.4"
pytest-asyncio = "^0.23.3"
pytest-cov = "^4.1.0"
ruff = "^0.1.9"
mypy = "^1.8.0"
This technology stack provides battle-tested, production-ready solutions for Python backend development in 2025.