Client. A long-distance passenger transport company selling tickets through a digital channel: on the order of hundreds of thousands of sales and over a million tickets issued, with payments and refunds that have to reconcile to the cent because it is real money from real people.
Approach
This case spans two links of the method —software engineering and data engineering— with no handoff between them: the same mind that designed how each event enters the system is the one that later modeled the financial data and the analytics layer that reads it. The first link —the sociotechnical reading— is present as a criterion, not as a separate deliverable: understanding that a refund is not a ticket with a negative sign, and that a sale can issue several tickets over time, is what organized the model before the first table was written. The fourth link —AI over the data— is outside the delivered scope: here intelligence is applied as a working instrument of the engineer, not as a product. The distinction is deliberate and part of the brand’s honesty.
The thesis that governs the work is that of data reliable by construction: in a financial backend it is not enough for the number to be there; it has to be possible to prove where it came from and to reconstruct it from the source if something breaks. That is why the system does not compute on what it receives and then discard it: it stores the raw event first, immutable, and only then derives the business model. What cannot be reconstructed cannot be audited.
The problem detected
The company read its financial operation through a legacy batch model that carried on the order of 21h lag: today’s reporting showed yesterday’s business. On that basis, reconciliation of sales, payments and refunds was done by hand, exporting CSV and Excel and cross-checking them against the provider’s ticketing platform. Each close depended on a person running the process without error, and each discrepancy was investigated by hand, with no traceability back to the original transaction.
The stated problem was “the data arrives late.” The real problem was prior to that: the system had no memory of the event. It worked on batch snapshots and derivations, not on the economic fact as it actually occurred. Without that memory, neither latency nor reconciliation had a real fix: any improvement was a patch over a process that could not prove its own result.
Functional analysis
Before building, I mapped what each object of the domain really means —not what the endpoint name says— because in a financial system misunderstood joins are paid in money:
| Object | What it represents | Unit of analysis |
|---|---|---|
Sale (sale) | The passenger’s complete commercial operation | sale |
| Ticket | The issued ticket; a sale can issue several | ticket / leg |
Payment (payment) | The movement of money backing the sale | transaction |
| Refund | The reimbursement; it is not a negative ticket, it is another fact | transaction |
| Manifest | The list of passengers per service/trip | manifest / service |
The analysis included an explicit account of what the integration does not guarantee: webhooks that may arrive duplicated, out of order, or not arrive at all; ticket.* events that appear standalone, without hanging off a transaction; and a provider API contract that evolves on their side. Documenting each of those failure modes was part of the analysis, because each one later became a design decision —idempotency, safety-net, versioned snapshot of the contract— and not a surprise in production.
Building the technical solution
The central piece is not a pipeline: it is a raw-first, event-driven architecture. The system receives the webhooks from the provider’s ticketing platform —sale, payment and refund transactions, and ticket.* events—, validates each one via HMAC, and persists it raw and immutable before interpreting it. The processing that derives the business model is idempotent: the same event, whether it arrives once or five times, produces the same state. That combination —verified signature, immutable raw, idempotent derivation— is what replaced the ~21h batch with near-real-time ingestion, sustaining on the order of 60–85 thousand sales and 5–8 thousand refunds per month (figures that grow with the operation).
On top of that raw layer sits a normalized, ledger-style financial model —sales, tickets, payments, refunds, manifests— which does distinguish each economic fact as its own entity. The reconciliation that used to be a hand-built Excel became a set of automated reconciliation and recovery jobs: the system detects what is missing and goes to fetch it, instead of waiting for a person to notice the gap. The integration was completed with JWT handling against the provider and a manifest sync over webhook with a scheduled safety-net that re-fetches whatever the webhook failed to deliver.
The base stack is FastAPI over PostgreSQL (SQLAlchemy async), deployed on GCP (Cloud Run, Cloud SQL, Secret Manager) in Dockerized form, with schema evolution governed by Alembic. One detail that matters: the bulk of the backend is Python, but the querying of transaction events was solved with a separate microservice in NestJS/TypeScript over MongoDB, which exposes the latest event per transaction identifier filtering by status (paid / cancelled) with Argentina timezone handling. The choice was not a fashion: it was using the right tool for a high-cardinality event query, without contaminating the transactional ledger.
Information and data layer
Data governance was design, not an annex. The analytics layer is a reconstructible piece: a bi_rebuild process that derives the reporting from the model, it does not accumulate it. If the business logic changes or a dashboard is in doubt, the layer is rebuilt from the raw facts instead of dragging dirty state along. That reconstruction feeds the business dashboards and the design of cubes for MicroStrategy —fact_ticket (coverage by route) and its variant with the manifest tag set—, each with its documented schema and its deployment runbook.
The criterion that holds it all together: traceability from the metric to the source. Any number on a dashboard can be traced back to the raw event that originated it, because that raw event was never deleted. In a financial domain, that is not an engineering luxury: it is the difference between a report you can defend in an audit and one you have to take on faith.
How the work was run
The work was carried out in 2026 with a code agent harness governed by its own instruments, not by improvised prompting. The concrete and verifiable:
- Living documentation as source of truth. The architecture, the OLTP and ingestion model, and the analytics layer live as versioned documents in the repo —not in one person’s head nor in a wiki that ages—. The agent works against that versioned source and not against its memory.
- Versioned risk register. Security and operations decisions —HMAC enforcement, guard of the auth key via Secret Manager, observability of the manifest re-fetch— are kept in a living register that evolves with the system, so that each mitigation stays auditable and not implicit.
- Provider contract snapshot versioned locally. The ticketing platform’s OpenAPI is kept as a snapshot in the repo, with an explicit update process. The data contract lives under version control on our side: when the provider changes, the change shows up in a diff, not in a production error.
- Automated jobs as discipline, not heroics. Reconciliation and recovery of missing data are scheduled, reproducible processes that do not depend on someone remembering to run them. The schema is versioned with Alembic migrations, not with manual changes against the database.
The point: AI is not in the product delivered to the client; it is in how I build, the way any serious engineer uses their toolset today. Showing it this way —factual, without adjectives— is what distinguishes real command of the tool from the fashionable discourse.
What this case proves
- A real financial backend: a raw-first, event-driven architecture, with HMAC signing, idempotency and a ledger-style model that distinguishes each economic fact —not a CRUD with good intentions.
- Reconstructible data engineering: an analytics layer that is derived from the source and rebuilt, with traceability from the metric to the raw event, ready to be defended in an audit.
- Stack versatility with judgment: Python for the transactional ledger and a NestJS/MongoDB microservice for the event query —the tool chosen for the problem, not out of habit.