Skip to content

Challenge 1 - Payment settlement pipeline” - Victor Farro#11

Open
victorfarro91 wants to merge 1 commit into
yaperos:mainfrom
victorfarro91:main
Open

Challenge 1 - Payment settlement pipeline” - Victor Farro#11
victorfarro91 wants to merge 1 commit into
yaperos:mainfrom
victorfarro91:main

Conversation

@victorfarro91
Copy link
Copy Markdown

1. El desafío elegido y por qué
Elegí el “Challenge 1 - Payment settlement pipeline” porque permite evaluar competencias clave que son críticas en sistemas reales:

• Diseño de arquitecturas event driven
• Manejo de consistencia eventual
• Implementación de sagas sin transacciones distribuidas
• Control de reintentos y duplicados
• Uso práctico de Kafka en producción
El problema no se resuelve correctamente con una arquitectura sincrónica tradicional, por lo que resulta un buen ejercicio para demostrar criterio arquitectónico más allá de la simple funcionalidad.


2. Decisiones arquitectónicas clave y alternativas descartadas
a. Arquitectura basada en eventos (Event Driven Architecture)
Decisión:
Se utilizó Kafka como backbone de eventos, publicando payment.created.v1 y permitiendo que distintos servicios consuman ese evento de forma independiente.
Justificación:
• Evita acoplar la API de pagos a servicios downstream.
• Permite escalar consumidores de manera independiente.
• Facilita agregar nuevos consumidores sin modificar código existente (como el servicio de notificaciones).
Alternativas descartadas:
• Orquestación sincrónica vía HTTP (API → fraude → contabilidad), descartada por:
o acoplamiento fuerte,
o propagación de fallos,
o baja extensibilidad.


b. Fan out con múltiples consumidores sobre el mismo tópico
Decisión:
Fraude, contabilidad y notificaciones consumen el mismo tópico (payment.created.v1) usando groupId distintos.
Justificación:
• Es el patrón natural de Kafka para fan out.
• No requiere duplicar tópicos.
• Cada consumidor mantiene su propia lógica y ciclo de vida.
Alternativas descartadas:
• Tópicos separados por consumidor, lo cual introduce duplicación, mayor complejidad y pérdida de flexibilidad.


c. Idempotencia explícita con processed_events
Decisión:
Cada consumidor valida si ya procesó un evento usando la tabla processed_events.
Justificación:
Kafka no garantiza exactly once en este escenario.
Sin esta validación, reintentos o reentregas podrían ejecutar la lógica varias veces.
Separar idempotencia técnica de estado de negocio evita:
• duplicados,
• corrupción de datos,
• efectos secundarios repetidos.
Alternativas descartadas:
• Confiar únicamente en offsets de Kafka.
• Ignorar reentregas (inválido en sistemas reales).


d. Modelo de saga con consistencia eventual
Decisión:
El estado final del pago se calcula en un servicio independiente (status-worker) que:
• observa los resultados parciales (payment_ack),
• decide el estado final,
• actualiza la tabla payments,
• publica eventos finales (payment.settled.v1, payment.failed.v1).
Justificación:
• Evita transacciones distribuidas.
• Acepta estados intermedios (pending).
• Garantiza convergencia determinística del sistema.
Alternativas descartadas:
• Two Phase Commit (demasiado costoso y frágil).
• Resolver estado en tiempo real desde los consumers (acopla responsabilidades).

e. Base de datos: elección y justificación
Elección: PostgreSQL.
Justificación:
• Soporta transacciones ACID necesarias para outbox e idempotencia.
• Permite consultas relacionales claras para modelar la saga.
• Es ampliamente usado en sistemas financieros.
• Integra fácilmente con Node.js y Kafka.
Se priorizó consistencia y claridad sobre soluciones NoSQL que no aportarían ventajas claras en este caso.


f. Orquestación: Temporal, Kafka o máquina de estados
Elección:
Orquestación propia basada en eventos + estado persistido (Status Saga).
Justificación:
• Kafka se usa como bus de eventos, no como orquestador.
• No se introdujo un motor externo como Temporal para mantener el stack liviano.
• El estado de la saga reside en la base de datos y evoluciona por eventos.
Este enfoque:
• Reduce complejidad operativa.
• Mantiene control explícito del dominio.
• Es adecuado para el tamaño y alcance del problema.


3. Qué haría diferente si tuviera más tiempo
Con más tiempo, se podrían incorporar:
• Timeouts de saga para pagos que no convergen.
• Retries de negocio con backoff y clasificación de errores.
• DLQ explícita para errores irrecuperables.
• Observabilidad (métricas, tracing distribuido).
• Contrato de eventos versionado usando schemas (Avro/Protobuf).
• Implementación con BIAN y Domain-driven design
• Seguridad de Apis.
La base actual está preparada para estas extensiones sin refactor mayor.


4. Limitaciones conocidas o atajos tomados
• No se implementó persistencia de notificaciones (notify es side effect only).
• No hay manejo de timeouts ni compensaciones complejas.
• El status worker utiliza polling periódico en lugar de un trigger totalmente reactivo.
• El alcance se limitó a un dominio de pagos para mantener claridad.
Estos atajos son conscientes y no comprometen la validez del diseño.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant