Estado: Aceptado
Fecha: 2025-11-14
Decisores: Equipo de Arquitectura
Reemplaza: Decisión previa de usar .NET con IIS
Necesitamos seleccionar una tecnología backend para implementar nuestros microservicios (Orders, Inventory, Payments, Notifications). Los requisitos incluyen:
- Soporte robusto para APIs REST
- Facilidad de desarrollo y mantenimiento
- Buena integración con message brokers
- Performance adecuado para nuestro caso de uso
- Ecosistema maduro con librerías para eventos, validación, ORM, etc.
Implementaremos los microservicios backend utilizando Python 3.12+ con FastAPI como framework principal para las APIs REST.
- Productividad: Sintaxis clara y concisa, desarrollo rápido
- Ecosistema Rico: Amplia variedad de librerías para cualquier necesidad
- Type Hints: Soporte moderno de tipos con Python 3.10+
- Comunidad: Gran comunidad y abundante documentación
- Versatilidad: Excelente para APIs, data processing, ML/AI
- Developer Experience: Fácil de aprender y mantener
- Async Support: Soporte nativo para operaciones asíncronas (asyncio)
- Performance: Menor performance raw que lenguajes compilados
- GIL: Global Interpreter Lock limita concurrencia con threads
- Deployment: Requiere runtime Python en el servidor
- Type Safety: Tipos opcionales, no enforced en runtime
- Performance: Uno de los frameworks Python más rápidos (comparable a Node.js)
- Modern Python: Aprovecha async/await y type hints
- Auto Documentation: OpenAPI/Swagger automático
- Data Validation: Pydantic integrado para validación de datos
- Type Safety: Validación basada en tipos en development time
- Dependency Injection: Sistema robusto de DI
- Standards-Based: Basado en OpenAPI y JSON Schema
- Relativamente Nuevo: Menos maduro que Django o Flask
- Async Required: Requiere entender async/await
- Menos Plugins: Ecosistema de plugins menor que Django
- Rechazado: Aunque excelente, requiere mayor overhead de infraestructura
- Menor velocidad de desarrollo
- Ecosistema más limitado para data science/ML (futuro)
- Considerado Seriamente: Excelente performance y ecosistema
- Rechazado: Python ofrece mejor experiencia para nuestro equipo
- Type safety menos natural que con Python type hints
- Rechazado: Mejor performance pero mayor curva de aprendizaje
- Menos flexible para rapid development
- Ecosistema más limitado
- Rechazado: Excesivo boilerplate
- Mayor overhead de memoria
- Desarrollo más lento
- Rechazado: Framework más pesado y opinionado
- Menor performance que FastAPI
- Incluye mucho que no necesitamos (ORM, admin, templates)
- Python: ^3.12 (latest stable)
- FastAPI: ^0.115.0
- Uvicorn: ASGI server para producción
- Pydantic: ^2.9.0 (validación de datos)
- SQLAlchemy: ^2.0 (ORM)
- Alembic: Migraciones de base de datos
- asyncpg: Driver PostgreSQL asíncrono
- PostgreSQL: Base de datos principal (database per service)
- Pika: Cliente RabbitMQ
- aio-pika: Cliente RabbitMQ asíncrono
- Celery: Para tareas asíncronas (opcional)
- Pydantic: Validación de schemas
- python-dotenv: Gestión de variables de entorno
- pytest: Framework de testing
- pytest-asyncio: Testing de código async
- httpx: Cliente HTTP para testing
- pytest-cov: Code coverage
- factory-boy: Test fixtures
- FastAPI: Auto-genera OpenAPI/Swagger
- OpenAPI: Especificación de API
- structlog: Logging estructurado
- prometheus-client: Métricas
- OpenTelemetry: Distributed tracing
- black: Code formatting
- ruff: Linting (reemplazo moderno de flake8)
- mypy: Type checking
- pre-commit: Git hooks para calidad
services/
├── orders-api/
│ ├── app/
│ │ ├── api/ # API endpoints
│ │ │ ├── v1/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── orders.py # Orders endpoints
│ │ │ │ └── health.py # Health check
│ │ │ └── deps.py # Dependencies (DI)
│ │ ├── core/ # Core configuration
│ │ │ ├── __init__.py
│ │ │ ├── config.py # Settings con Pydantic
│ │ │ ├── security.py # Auth & security
│ │ │ └── events.py # Event bus setup
│ │ ├── domain/ # Domain layer
│ │ │ ├── __init__.py
│ │ │ ├── models.py # Domain models (Pydantic)
│ │ │ ├── entities.py # Business entities
│ │ │ └── value_objects.py # Value objects
│ │ ├── application/ # Application layer
│ │ │ ├── __init__.py
│ │ │ ├── commands.py # Command handlers
│ │ │ ├── queries.py # Query handlers
│ │ │ └── services.py # Application services
│ │ ├── infrastructure/ # Infrastructure layer
│ │ │ ├── __init__.py
│ │ │ ├── database.py # DB setup
│ │ │ ├── repositories.py # Repository implementations
│ │ │ ├── messaging.py # Message broker
│ │ │ └── cache.py # Cache (Redis)
│ │ ├── events/ # Event definitions
│ │ │ ├── __init__.py
│ │ │ ├── handlers.py # Event handlers
│ │ │ ├── publishers.py # Event publishers
│ │ │ └── schemas.py # Event schemas
│ │ ├── schemas/ # API schemas (Pydantic)
│ │ │ ├── __init__.py
│ │ │ ├── requests.py # Request schemas
│ │ │ └── responses.py # Response schemas
│ │ ├── utils/ # Utilities
│ │ │ └── __init__.py
│ │ └── main.py # Application entry point
│ ├── tests/
│ │ ├── unit/
│ │ ├── integration/
│ │ └── conftest.py
│ ├── alembic/ # Database migrations
│ │ ├── versions/
│ │ └── env.py
│ ├── .env.example
│ ├── .dockerignore
│ ├── Dockerfile
│ ├── pyproject.toml # Dependencies & config
│ ├── README.md
│ └── .copilot-context.md
- API Layer (
api/): Controladores FastAPI, validación de entrada - Application Layer (
application/): Use cases, orchestration - Domain Layer (
domain/): Business logic, entities, value objects - Infrastructure Layer (
infrastructure/): Database, messaging, external services
- Repository Pattern: Abstracción de acceso a datos
- Dependency Injection: FastAPI's DI system
- Command/Query Separation (CQRS): Separar reads y writes cuando convenga
- Event-Driven: Comunicación asíncrona entre servicios
- Saga Pattern: Para transacciones distribuidas
# infrastructure/messaging.py
import aio_pika
from typing import Callable
class EventBus:
def __init__(self, connection_url: str):
self.connection_url = connection_url
self.connection = None
self.channel = None
async def connect(self):
self.connection = await aio_pika.connect_robust(self.connection_url)
self.channel = await self.connection.channel()
async def publish(self, exchange: str, routing_key: str, message: dict):
await self.channel.default_exchange.publish(
aio_pika.Message(body=json.dumps(message).encode()),
routing_key=routing_key
)
async def subscribe(self, queue: str, callback: Callable):
queue = await self.channel.declare_queue(queue, durable=True)
await queue.consume(callback)- GET
/api/v1/orders- List orders - GET
/api/v1/orders/{order_id}- Get single order - POST
/api/v1/orders- Create order - PUT
/api/v1/orders/{order_id}- Update order - DELETE
/api/v1/orders/{order_id}- Delete order - GET
/health- Health check - GET
/metrics- Prometheus metrics
{
"success": true,
"data": {...},
"error": null,
"metadata": {
"timestamp": "2025-11-14T10:30:00Z",
"request_id": "uuid"
}
}{
"success": false,
"data": null,
"error": {
"code": "ORDER_NOT_FOUND",
"message": "Order with ID 123 not found",
"details": {}
},
"metadata": {...}
}# core/config.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
# App
app_name: str = "Orders API"
debug: bool = False
api_v1_prefix: str = "/api/v1"
# Database
database_url: str
# RabbitMQ
rabbitmq_url: str
# Redis
redis_url: str
class Config:
env_file = ".env"
settings = Settings()- Test business logic en domain layer
- Test services en application layer
- Usar mocks para dependencies
- Test endpoints de API
- Test event handlers
- Usar test database
- Validar schemas de eventos
- Validar API contracts
Cada microservicio tendrá su Dockerfile:
FROM python:3.12-slim
WORKDIR /app
# Install dependencies
COPY pyproject.toml ./
RUN pip install poetry && poetry install --no-dev
# Copy app
COPY app/ ./app/
# Run
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]Para desarrollo local con todos los servicios
- Desarrollo rápido y productivo
- Excelente experiencia de desarrollador
- Auto-documentación con OpenAPI/Swagger
- Type safety con Pydantic
- Performance adecuado para nuestras necesidades
- Fácil integración con message brokers
- Excelente para testing
- Futuro-proof para ML/AI features
- Menor performance que lenguajes compilados (mitigado con async)
- Requiere disciplina con type hints
- GIL puede ser limitante en casos extremos (mitigado con arquitectura de microservicios)
- Deployment requiere gestionar Python runtime
- Crear estructura de proyecto para cada microservicio
- Setup de FastAPI con configuración básica
- Implementar health checks
- Setup de database con SQLAlchemy
- Configurar logging estructurado
- Implementar domain models
- Implementar repositories
- Crear endpoints básicos CRUD
- Setup de event bus
- Implementar event handlers
- Integrar todos los microservicios
- Implementar sagas para flujos complejos
- Testing end-to-end
- Performance tuning
- Monitoring y observability
- Security hardening
- CI/CD pipeline
- Documentation
- Usar Python 3.12+ para mejor performance y features
- Activar strict mode en mypy
- Usar async/await para todas las operaciones I/O
- Implementar idempotency keys en event handlers
- Documentar todos los endpoints con docstrings
- Usar environment variables para toda configuración