SYS-01 / DOSSIER
Commerce Operations Lab
Laboratorio técnico desplegado y operado para probar entrega, recuperación y observabilidad de un backend distribuido en un único host.
Java · Spring Boot · Kafka · PostgreSQL · Docker
SYS-01 / REFERENCIA DE ARQUITECTURA
Topología de ejecución
TRANSACTIONAL OUTBOX · AT-LEAST-ONCE · IDEMPOTENT CONSUMER
-
ORDER API
-
03 / KAFKA
orders.received.v1 -
ORDER WORKER
Overview
Commerce Operations Lab es un laboratorio técnico desplegado y operado, no una plataforma enterprise de producción ni un sistema HA. Ejecuta un backend distribuido en una VM con Docker Compose y un único host. El caso de estudio se utiliza para probar build, entrega, recuperación y observabilidad con señales locales y desechables.
Architecture
La referencia de arquitectura es: order-api recibe la orden y confirma en su PostgreSQL la orden junto con el evento en outbox_events mediante una transacción; un publicador entrega el evento a Kafka con semántica at-least-once; order-worker consume y procesa de forma idempotente, registrando received_orders en su PostgreSQL separado. API y worker tienen bases de datos distintas. Kafka usa el tópico orders.received.v1.
Delivery
La entrega estática sigue este orden: GitHub Actions → verify/build → imagen en GHCR identificada por SHA → SSH restringido → validación del candidato → readiness health gate → activación o rollback. El flujo de publicación se ejecuta desde main. El acceso usa forced command, sudo restringido y un exclusive lock; también conserva un last-successful marker. No se documentan aquí hosts, IPs, usuarios, fingerprints, secretos ni comandos.
Recovery
Hay dos operaciones distintas. El release rollback cambia únicamente las imágenes y no restaura datos. La data recovery parte de un backup lógico de PostgreSQL, valida checksum y manifest, hace un restore aislado y verifica schema, invariantes y cleanup.
El resultado observado del drill fue API NON_EMPTY, worker NON_EMPTY, overall PASS y cleanup PASS, con una duración observada de 6066 ms. Ese tiempo no es un SLA ni un RTO.
Observability
Las señales locales incluyen HTTP, JVM, Hikari, outbox pending y oldest age, y worker processed y failed. Se instrumentan con Prometheus, Grafana, node_exporter y Alertmanager. Grafana queda accesible por loopback/SSH; Prometheus y Alertmanager no son públicos. No se incluyen logs, tracing, exporters de PostgreSQL o Kafka ni alerting externo: son señales locales, desechables y de un único host.
Incident
El resumen de incidente OrderWorkerUnavailable es: condición de objetivo no disponible durante 2 minutos; healthy → down → pending → firing → investigation → recovery → resolved. El worker quedó UP, la alerta inactive/resolved y API, DB y Kafka quedaron healthy. El release no cambió.
Registro detallado: INC-01.001 — Order worker unavailable.
Decisions & limitations
Las decisiones se renderizan con los ADR existentes. Está implementado: entrega por SHA, rollback de release, restore drill, métricas y alerting local. No está implementado: HA, Kubernetes, DR off-host, external paging, centralized logging ni tracing.
Decisiones registradas
- ADR-01.001 — Idempotencia en la recepción de órdenes
La recepción de órdenes usa externalReference y una restricción UNIQUE en PostgreSQL para resolver recepciones repetidas y concurrentes.
- ADR-01.002 — Registrar eventos con transactional outbox
La recepción de órdenes persiste el estado y el evento OrderReceived de forma atómica mediante un transactional outbox.
- ADR-01.003 — Consumo idempotente mediante identidad de la orden
El consumidor deduplica OrderReceived mediante order_id como clave primaria y llama a acknowledge sólo después de que materialize() retorna sin excepción.