gonzalo@flores — ~/portfolio/ingesta-financiera-transporte EN
Gonzalo Flores Kemec

← Portfolio

Platform

Backend financiero orientado a eventos: de un batch con 21 horas de lag a ingesta near-real-time

Construí el backend event-driven que ingesta ventas, tickets, pagos, refunds y manifiestos desde la plataforma de ticketing del proveedor con webhooks validados por HMAC y almacenamiento raw-first inmutable, un modelo financiero tipo ledger y una capa analítica reconstruible que alimenta la reportería del negocio.

./caso --ficha
cliente
Empresa de transporte de pasajeros de larga distancia con venta de pasajes digital
rol
Backend & Data Engineer
sector
Transporte de pasajeros · ticketing
eslabones
Ingeniería de software · Ingeniería de datos
stack
FastAPI · PostgreSQL / SQLAlchemy async · GCP (Cloud Run, Cloud SQL, Secret Manager) · Alembic · NestJS / MongoDB · MicroStrategy (BI)

Caso real con el cliente anonimizado por confidencialidad. Se describe el problema de negocio, el método y las decisiones; no se publica código ni dato sensible.

Cliente. Una empresa de transporte de pasajeros de larga distancia que vende pasajes por canal digital: del orden de cientos de miles de ventas y más de un millón de tickets emitidos, con pagos y devoluciones que tienen que cuadrar al peso porque son plata real de gente real.

Enfoque

Este caso recorre dos eslabones del método —ingeniería de software e ingeniería de datos— sin handoff entre ellos: la misma cabeza que diseñó cómo entra cada evento al sistema es la que después modeló el dato financiero y la capa analítica que lo lee. El primer eslabón —la lectura sociotécnica— está presente como criterio, no como entregable separado: entender que un refund no es un ticket con signo negativo, y que una venta puede emitir varios tickets a lo largo del tiempo, es lo que ordenó el modelo antes de escribir la primera tabla. El cuarto eslabón —la IA sobre el dato— queda fuera del alcance entregado: acá la inteligencia se aplica como instrumento de trabajo del ingeniero, no como producto. La distinción es deliberada y es parte de la honestidad de la marca.

La tesis que gobierna el trabajo es la del dato confiable por construcción: en un backend financiero no alcanza con que el número esté; tiene que poder demostrarse de dónde salió y reconstruirse desde la fuente si algo se rompe. Por eso el sistema no calcula sobre lo que recibe y lo descarta: guarda primero el evento crudo, inmutable, y recién después deriva el modelo de negocio. Lo que no se puede reconstruir, no se puede auditar.

El problema detectado

La empresa leía su operación financiera con un modelo batch legacy que arrastraba del orden de 21 horas de lag: la reportería de hoy mostraba el negocio de ayer. Sobre esa base, la conciliación de ventas, pagos y devoluciones se resolvía a mano, exportando CSV y Excel y cruzándolos contra la plataforma de ticketing del proveedor. Cada cierre dependía de que una persona corriera el proceso sin equivocarse, y cada discrepancia se investigaba a mano, sin trazabilidad hacia la transacción original.

El problema declarado era “los datos llegan tarde”. El problema real era anterior: el sistema no tenía memoria del evento. Trabajaba sobre fotos batch y derivaciones, no sobre el hecho económico tal como ocurrió. Sin esa memoria, ni la latencia ni la conciliación tenían arreglo de fondo: cualquier mejora era un parche sobre un proceso que no podía demostrar su propio resultado.

Relevamiento funcional

Antes de construir, mapeé qué significa de verdad cada objeto del dominio —no qué dice el nombre del endpoint—, porque en un sistema financiero los empalmes mal entendidos se pagan en plata:

ObjetoQué representaUnidad de análisis
Venta (sale)La operación comercial completa del pasajeroventa
TicketEl pasaje emitido; una venta puede emitir variosticket / tramo
Pago (payment)El movimiento de dinero que respalda la ventatransacción
RefundLa devolución; no es un ticket negativo, es otro hechotransacción
ManifiestoLa lista de pasajeros por servicio/viajemanifiesto / servicio

El relevamiento incluyó un análisis explícito de lo que la integración no garantiza: webhooks que pueden llegar duplicados, fuera de orden o no llegar; eventos de ticket.* que aparecen standalone, sin venir colgados de una transacción; y un contrato de API del proveedor que evoluciona del lado de ellos. Documentar cada uno de esos modos de falla fue parte del relevamiento, porque cada uno se convirtió después en una decisión de diseño —idempotencia, safety-net, snapshot versionado del contrato— y no en una sorpresa en producción.

Construcción de la solución técnica

La pieza central no es un pipeline: es una arquitectura raw-first orientada a eventos. El sistema recibe los webhooks de la plataforma de ticketing del proveedor —transacciones de venta, pago y devolución, y eventos ticket.*—, valida cada uno por HMAC, y lo persiste crudo e inmutable antes de interpretarlo. El procesamiento que deriva el modelo de negocio es idempotente: el mismo evento, llegue una o cinco veces, produce el mismo estado. Esa combinación —firma verificada, crudo inmutable, derivación idempotente— es lo que reemplazó al batch de ~21 horas por una ingesta near-real-time, sosteniendo del orden de 60–85 mil ventas y 5–8 mil devoluciones por mes (cifras que crecen con la operación).

Sobre ese crudo se asienta un modelo financiero normalizado tipo ledgersales, tickets, payments, refunds, manifests— que sí distingue cada hecho económico como entidad propia. La reconciliación que antes era un Excel a mano pasó a ser un conjunto de jobs automatizados de reconciliación y recuperación: el sistema detecta lo que falta y lo va a buscar, en lugar de esperar que una persona note el faltante. La integración se completó con manejo de JWT contra el proveedor y un sync de manifiestos por webhook con un safety-net programado que re-busca lo que el webhook no haya entregado.

El stack base es FastAPI sobre PostgreSQL (SQLAlchemy async), desplegado en GCP (Cloud Run, Cloud SQL, Secret Manager) de forma Dockerizada, con la evolución de esquema gobernada por Alembic. Un detalle que importa: el grueso del backend es Python, pero la consulta de eventos de transacciones se resolvió con un microservicio aparte en NestJS/TypeScript sobre MongoDB, que expone el último evento por identificador de transacción filtrando por estado (paid / cancelled) con manejo de zona horaria de Argentina. La elección no fue de moda: fue usar la herramienta adecuada para una consulta de eventos de alta cardinalidad, sin contaminar el ledger transaccional.

Capa de información y datos

El gobierno del dato fue diseño, no anexo. La capa analítica es una pieza reconstruible: un proceso bi_rebuild que deriva la reportería desde el modelo, no la acumula. Si la lógica de negocio cambia o un tablero queda en duda, la capa se reconstruye desde los hechos crudos en lugar de arrastrar estados sucios. Esa reconstrucción alimenta los tableros del negocio y el diseño de cubos para MicroStrategyfact_ticket (alcance por ruta) y su variante con el set de tags de manifiesto—, cada uno con su esquema documentado y su runbook de despliegue.

El criterio que sostiene todo: trazabilidad de la métrica a la fuente. Cualquier número de un tablero puede rastrearse hasta el evento crudo que lo originó, porque ese crudo nunca se borró. En un dominio financiero, eso no es un lujo de ingeniería: es la diferencia entre un reporte que se puede defender frente a una auditoría y uno que hay que creer de palabra.

Cómo se condujo el trabajo

El trabajo se ejecutó en 2026 con un harness de agentes de código gobernado por instrumentos propios, no por prompting improvisado. Lo concreto y verificable:

  • Documentación viva como fuente de verdad. La arquitectura, el modelo OLTP e ingesta, y la capa analítica viven como documentos versionados en el repo —no en la cabeza de una persona ni en un wiki que envejece—. El agente trabaja contra esa fuente versionada y no contra su memoria.
  • Registro de riesgos versionado. Las decisiones de seguridad y operación —enforcement de HMAC, guard de la auth key vía Secret Manager, observabilidad del re-fetch de manifiestos— se llevan en un registro vivo que evoluciona con el sistema, de modo que cada mitigación quede auditable y no implícita.
  • Snapshot del contrato del proveedor versionado localmente. El OpenAPI de la plataforma de ticketing se guarda como snapshot en el repo, con un proceso explícito de actualización. El contrato del dato vive bajo control de versiones del lado nuestro: cuando el proveedor cambia, el cambio se ve en un diff, no en un error de producción.
  • Jobs automatizados como disciplina, no como heroísmo. La reconciliación y la recuperación de faltantes son procesos programados, reproducibles, que no dependen de que alguien se acuerde de correrlos. El esquema se versiona con migraciones Alembic, no con cambios manuales sobre la base.

El punto: la IA no está en el producto entregado al cliente; está en cómo construyo, como cualquier ingeniero serio usa hoy su instrumental. Mostrarlo así —factual, sin adjetivos— es lo que distingue el dominio real de la herramienta del discurso de moda.

Qué prueba este caso

  • Backend financiero de verdad: una arquitectura raw-first orientada a eventos, con firma HMAC, idempotencia y un modelo tipo ledger que distingue cada hecho económico —no un CRUD con buena intención.
  • Data engineering reconstruible: una capa analítica que se deriva desde la fuente y se reconstruye, con trazabilidad de la métrica al evento crudo, lista para defenderse frente a una auditoría.
  • Versatilidad de stack con criterio: Python para el ledger transaccional y un microservicio NestJS/MongoDB para la consulta de eventos —la herramienta elegida por el problema, no por costumbre.