Monolithic Python App to FastAPI Services
A guide to decomposing monolithic Python applications into FastAPI microservices for better scalability.
Executive Summary
A SaaS company's monolithic Python app was failing at 1M users—500ms latency, 30% error rate at peak. Over 10 months, they decomposed it into 20 FastAPI microservices, achieving 50ms latency and 99.99% uptime. This guide covers service extraction, shared state management, and deployment orchestration.
Why Migrate from Monolithic Python
The monolith had grown to 300K lines over 5 years. Deployment took 2 hours, and any bug could crash the entire system.
- → 500ms average latency (user frustration)
- → 30% error rate at peak load (5-8 PM)
- → 2-hour deployment window (weekly releases only)
- → 15 engineers blocked by merge conflicts
FastAPI Microservices Readiness
The team spent 2 months on preparation: DDD workshops, setting up Kubernetes, and training 15 engineers on FastAPI.
- • Domain-driven design (20 services identified)
- • Kubernetes cluster (EKS, 50 nodes)
- • API gateway (Kong) for routing
- • FastAPI training for 15 engineers (4 weeks)
- • Service mesh (Istio) for observability
Python Monolith Assessment
The monolith had 300K lines of Python (Flask), 100 database tables, and 50,000 daily users. The biggest bottlenecks were checkout (30% of errors) and reporting (CPU-bound).
Technical Debt
- • Flask sync views (blocking)
- • Single database (connection pool exhausted)
- • Monolithic deployment (2 hours, 20% failure rate)
- • No service boundaries (tight coupling)
Risks
- • Distributed transaction complexity (saga)
- • Data consistency across services
- • Performance regression (network calls)
- • Team async learning curve
Target FastAPI Microservices
The target was 20 FastAPI services, each with own database, async all the way.
10-Month Monolith to Microservices
Step 1: Phase 1: Foundation (Month 1-2)
DDD workshops, Kubernetes cluster, API gateway, FastAPI training.
Step 2: Phase 2: Reporting Service (Month 3-4)
Extracted reporting—low criticality, proved architecture.
Step 3: Phase 3: Checkout Service (Month 5-7)
Extracted checkout—high criticality, required saga pattern.
Step 4: Phase 4: Remaining Services (Month 8-10)
Extracted remaining 18 services incrementally.
Database Decomposition
Started with shared database (schema per service), split to separate databases after 6 months.
- • Shared database initially (lower risk)
- • Schema per service in same PostgreSQL
- • Dual writes for 4 weeks per service
- • Split to separate databases after services stable
Common Python Monolith Migration Mistakes
Not using async database drivers
Impact: FastAPI services still blocking (no performance gain)
Prevention: asyncpg + SQLAlchemy 2.0 async
Extracting services by technical layer
Impact: Services still coupled (no benefit)
Prevention: Domain-driven design (checkout, reporting, users)
Synchronous inter-service communication
Impact: Latency cascade (5 services = 500ms)
Prevention: Async events (Kafka) for non-critical paths
No distributed tracing initially
Impact: Unable to debug cross-service latency (weeks of firefighting)
Prevention: Jaeger from day one
Migration Success Metrics
Who Should Lead Monolith to FastAPI Migration
Recommended Roles
Required Experience
- • Successfully decomposed 1+ Python monolith
- • FastAPI and async Python expertise
- • Kubernetes and service mesh
- • Team leadership for 15+ engineers
Related Roles
Frequently Asked Questions
- How many microservices should we create?
- 20-30 for 300K lines of code. Too few services defeats purpose, too many adds overhead.
- Should we use shared or per-service databases?
- Start shared (schema per service), split later. Reduces migration risk.
- How to handle cross-service transactions?
- Saga pattern with compensating transactions. Avoid distributed transactions (2PC).