Lesson 38 of 40
Architecture
Expert
โฑ 35 min
Microservices Architecture in Python
Design Python microservices with FastAPI, service discovery, message queues with RabbitMQ/Kafka, circuit breakers, and distributed tracing.
Part 1: What You Will Learn
- Separate a larger application into independently deployable services.
- Give each service a small, well-defined responsibility.
- Call another service with an HTTP client.
- Understand why timeouts, retries, queues, tracing, and circuit breakers become important in distributed systems.
Part 2: Inventory Service
from fastapi import FastAPI, HTTPException
app = FastAPI(title="Inventory Service")
stock = {
"P100": 8,
"P200": 0,
}
@app.get("/stock/{product_id}")
async def get_stock(product_id: str) -> dict:
if product_id not in stock:
raise HTTPException(status_code=404, detail="Unknown product")
return {
"product_id": product_id,
"quantity": stock[product_id],
"available": stock[product_id] > 0,
}Part 3: Order Service Calling Inventory
import httpx
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI(title="Order Service")
INVENTORY_URL = "http://127.0.0.1:8001"
class OrderRequest(BaseModel):
product_id: str
quantity: int
@app.post("/orders")
async def create_order(order: OrderRequest) -> dict:
timeout = httpx.Timeout(3.0)
try:
async with httpx.AsyncClient(timeout=timeout) as client:
response = await client.get(
f"{INVENTORY_URL}/stock/{order.product_id}"
)
response.raise_for_status()
except httpx.HTTPError as exc:
raise HTTPException(
status_code=503,
detail="Inventory service unavailable",
) from exc
inventory = response.json()
if inventory["quantity"] < order.quantity:
raise HTTPException(
status_code=409,
detail="Insufficient stock",
)
return {
"status": "accepted",
"product_id": order.product_id,
"quantity": order.quantity,
}pip install fastapi httpx "uvicorn[standard]"
Part 4: Production Architecture Concerns
- Timeouts: never let one failed service block another indefinitely.
- Retries: retry only operations that are safe to repeat, with limits and backoff.
- Circuit breakers: temporarily stop calls to a repeatedly failing dependency.
- Message queues: RabbitMQ or Kafka can decouple work that does not need an immediate HTTP response.
- Distributed tracing: propagate trace IDs so one request can be followed across several services.
Part 5: Hands-On Practice
Mini project โ Order Microservices. Run the inventory service on port 8001 and the order service on port 8002. Add a payment service, then publish an order.created event to a queue instead of making every downstream action synchronous.
Part 6: Next Steps
After experimenting with service failures and timeouts, continue to Lesson 39 to secure Python applications and their credentials.
๐ Want the complete guide with projects?
Get the book โ