| name | Microservices |
| description | Architectural style structuring applications as loosely coupled, independently deployable services |
| category | software-development |
Microservices
What I do
I provide an architectural approach that structures applications as a collection of small, independent, loosely coupled services. Each microservice owns its business logic and data, communicating with other services through well-defined APIs. This enables teams to develop, deploy, and scale services independently, supporting continuous delivery and rapid iteration. I help design service boundaries, define communication patterns, and manage distributed system complexity.
When to use me
Microservices are appropriate for large, complex applications requiring multiple teams, when rapid iteration is critical, or when different components have varying scalability needs. Use microservices when you need technology heterogeneity or when different parts of the system benefit from different databases or frameworks. Avoid microservices for simple applications, startups needing rapid iteration, or teams without DevOps capabilities.
Core Concepts
- Service Decomposition: Splitting monolith into independent services
- API-First Design: Defining contracts before implementation
- Service Discovery: Dynamic location of service instances
- Load Balancing: Distributing requests across service replicas
- Circuit Breaking: Preventing cascade failures
- Distributed Tracing: Tracking requests across services
- Configuration Management: Centralized service configuration
- Health Checks: Monitoring service status
- Graceful Degradation: Maintaining functionality during failures
- Feature Flags: Controlling feature rollout
Code Examples
Service Definition with FastAPI
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel, EmailStr
from typing import Optional
from uuid import UUID, uuid4
from datetime import datetime
app = FastAPI(
title="User Service",
description="Manages user accounts and profiles",
version="1.0.0"
)
class UserCreate(BaseModel):
email: EmailStr
name: str
password: str
class UserResponse(BaseModel):
id: UUID
email: EmailStr
name: str
created_at: datetime
is_active: bool = True
class UserUpdate(BaseModel):
name: Optional[str] = None
email: Optional[EmailStr] = None
users_db: dict[UUID, dict] = {}
@app.post("/users", response_model=UserResponse, status_code=201)
async def create_user(user_data: UserCreate) -> UserResponse:
for user in users_db.values():
user[] == user_data.email:
HTTPException(status_code=, detail=)
user_id = uuid4()
user = {
: user_id,
: user_data.email,
: user_data.name,
: hash_password(user_data.password),
: datetime.utcnow(),
:
}
users_db[user_id] = user
UserResponse(**user)
() -> UserResponse:
user_id users_db:
HTTPException(status_code=, detail=)
UserResponse(**users_db[user_id])
() -> UserResponse:
user_id users_db:
HTTPException(status_code=, detail=)
user = users_db[user_id]
updates.name:
user[] = updates.name
updates.email:
user[] = updates.email
UserResponse(**user)
() -> :
user_id users_db:
HTTPException(status_code=, detail=)
users_db[user_id][] =
() -> :
hashlib
hashlib.sha256(password.encode()).hexdigest()
Service Discovery with Consul
from consul import Consul
import requests
from typing import Optional
class ServiceRegistry:
def __init__(self, host: str = "localhost", port: int = 8500):
self.consul = Consul(host=host, port=port)
self.service_name = "user-service"
self.service_port = 8080
def register(self, instance_id: str, health_check_url: str) -> None:
self.consul.agent.service.register(
name=self.service_name,
service_id=instance_id,
port=self.service_port,
check={
"http": health_check_url,
"interval": "10s",
"timeout": "5s",
"deregistercriticalserviceafter": "30s"
}
)
def deregister(self, instance_id: str) -> None:
self.consul.agent.service.deregister(instance_id)
def get_all_instances(self) -> list[]:
services = .consul.agent.service.get_all()
[
{: s[], : s[]}
s services.values()
s[] == .service_name
]
() -> []:
instances = .get_all_instances()
instances[] instances
:
():
.registry = registry
._cache: [] = []
() -> :
._cache = .registry.get_all_instances()
() -> :
._cache:
._refresh_cache()
._cache:
ServiceUnavailable()
instance = ._cache[]
Distributed Configuration
from dataclasses import dataclass
from typing import Protocol, Optional
import yaml
@dataclass
class ServiceConfig:
service_name: str
host: str
port: int
database_url: str
redis_url: str
log_level: str
retry_max_attempts: int
timeout_seconds: int
class ConfigurationManager:
def __init__(self, config_path: str = "config.yaml"):
self.config_path = config_path
self._config: Optional[ServiceConfig] = None
def load(self) -> ServiceConfig:
with open(self.config_path) as f:
raw = yaml.safe_load(f)
self._config = ServiceConfig(
service_name=raw["service"]["name"],
host=raw["service"]["host"],
port=raw["service"]["port"],
database_url=self._resolve_env(raw["database"]["url"]),
redis_url=self._resolve_env(raw[][]),
log_level=raw.get(, {}).get(, ),
retry_max_attempts=raw.get(, {}).get(, ),
timeout_seconds=raw.get(, {}).get(, )
)
._config
() -> :
(value, ) value.startswith() value.endswith():
env_var = value[:-]
._get_env(env_var, value)
value
() -> :
os
os.getenv(var, default)
() -> ServiceConfig:
._config :
.load()
._config
:
():
.flags = {
: ,
: ,
: ,
}
.config = config
() -> :
.flags.get(flag_name, )
() -> :
.flags[flag_name] =
Health Check Endpoints
from fastapi import APIRouter, Response
from pydantic import BaseModel
from datetime import datetime
import psutil
import subprocess
health_router = APIRouter()
class HealthStatus(BaseModel):
status: str
version: str
timestamp: str
checks: dict
class ComponentHealth(BaseModel):
status: str
latency_ms: float
details: Optional[dict] = None
@health_router.get("/health", response_model=HealthStatus)
async def health_check() -> HealthStatus:
checks = {
"database": check_database(),
"cache": check_cache(),
"external_api": check_external_api(),
}
overall_status = "healthy" if all(
c.status == "healthy" for c in checks.values()
) else "degraded"
return HealthStatus(
status=overall_status,
version="1.0.0",
timestamp=datetime.utcnow().isoformat(),
checks={k: c.model_dump() for k, c in checks.items()}
)
@health_router.get()
() -> Response:
Response(status_code=, content=)
() -> Response:
checks = [, ]
all_ready = (check_component(c) c checks)
Response(
status_code= all_ready ,
content= all_ready
)
() -> ComponentHealth:
time
start = time.time()
latency = (time.time() - start) *
ComponentHealth(status=, latency_ms=latency)
() -> ComponentHealth:
ComponentHealth(status=, latency_ms=)
() -> ComponentHealth:
ComponentHealth(status=, latency_ms=)
API Gateway Aggregation
from fastapi import FastAPI, HTTPException
from httpx import AsyncClient, Timeout
from typing import Any
app = FastAPI()
class APIGateway:
def __init__(self):
self.services = {
"users": "http://user-service:8080",
"orders": "http://order-service:8080",
"inventory": "http://inventory-service:8080",
}
async def aggregate_order_details(
self,
client: AsyncClient,
order_id: str
) -> dict[str, Any]:
order_response = await client.get(
f"{self.services['orders']}/orders/{order_id}",
timeout=Timeout(5.0)
)
if order_response.status_code != 200:
raise HTTPException(404, "Order not found")
order_data = order_response.json()
user_response = await client.get(
f"{self.services['users']}/users/{order_data['user_id']}"
)
order_data["user"] = user_response.json()
items_with_inventory = []
item order_data[]:
inv_response = client.get(
)
item[] = inv_response.json().get()
items_with_inventory.append(item)
order_data[] = items_with_inventory
order_data
() -> :
AsyncClient() client:
gateway = APIGateway()
gateway.aggregate_order_details(client, order_id)
Best Practices
- Start Simple: Don't microservices until you need them
- Design APIs First: Contract-driven development
- Separate Data: Each service owns its database
- Graceful Degradation: Handle failures without total system failure
- Observability: Logs, metrics, and tracing for all services
- Automate Everything: CI/CD pipelines for each service
- Containerize Services: Docker for consistent deployments
- API Versioning: Support backward compatibility
- Security: Auth at gateway, service-to-service auth
- Failure Modes: Design for partial failures
- Documentation: OpenAPI specs for all services
- Team Ownership: Each team owns their services end-to-end