Get In touch
Feel free to email me at hi@riteshr.com.np for counsuting work, and I'll get back to you.
A financial reconciliation platform built to automate the ingestion, processing, matching, and investigation of transactions across banking channels and external transaction sources — designed to answer, at scale, the question every digital bank eventually has to answer: *can we prove that every transaction recorded by one system is accurately accounted for everywhere else it touches?*
As banks moved transactions from physical branches to digital and self-service channels, transaction volume grew fast — and so did the number of systems generating records of the same event. ATM networks, mobile banking, core banking, and payment processors each produced their own version of a transaction, often in incompatible formats.
That created operational questions that used to be cheap to answer and were quickly becoming expensive:
The hard part wasn't comparing two files — it was building an engine that could ingest large volumes of financial records from different systems and formats while preserving data integrity end to end. An ATM log, for instance, could contain fields that had no direct equivalent in the corresponding core banking record.
That meant the system had to:
In practice, this meant the system needed to behave less like a CRUD application and more like a transaction-processing engine.
I was responsible for the architecture and development of the platform, not just individual features. My work included:
The central architectural responsibility: make sure a transaction could be traced from its original source through to its final reconciliation state without losing that chain.
At 5M+ transactions/day, this wasn't a script that loads two files into memory and diffs them — it was a system that had to continuously ingest, store, identify, and reconcile records without the database becoming the bottleneck. That reframed the problem from "how do we reconcile two files" to "how do we build an engine that can do this indefinitely, at increasing volume, without a redesign."
Simple archiving wasn't a viable answer to that question. Financial records carry regulatory and investigative requirements that mean data can't just be pushed off into cold storage and forgotten — it has to stay live, queryable, and traceable indefinitely. So instead of relying on ever-growing monolithic tables, I designed a middleware engine that broke incoming data down and created the underlying tables dynamically, without manual schema intervention as new sources or volume grew. The middleware sat between ingestion and storage, deciding how a given batch of transaction data should be structured and partitioned at the table level as it arrived, rather than requiring that structure to be predefined and maintained by hand.
That same middleware layer also drove reporting. Rather than relying on precomputed or scheduled reports, results were fetched dynamically based on the nature of the transaction and the requested time duration — so an operator querying a specific transaction type over a specific window wasn't scanning against static, generalized report tables, but pulling against structures shaped for that kind of query. This kept reporting responsive even as the underlying data volume kept growing.
Hard-coding every source's format would have made the system unmaintainable. Configurable mapping let the ingestion layer stay flexible while the reconciliation engine worked against one consistent model — new sources could be onboarded through configuration, not a rewrite.
When a discrepancy occurred, an operator needed to trace it: where the transaction originated, what transformations were applied, whether it had already been processed or matched, and why reconciliation failed. Retaining raw ATM logs separately from structured, processed transaction data gave the system a clean separation between source evidence and processed state — critical for investigation, not just for reconciliation itself.
Card numbers and related financial information were encrypted before storage, with access gated by user permissions. Security had to be part of the data model from the start, not layered on afterward.
A transaction isn't always just debit = credit. The engine needed to recognize related operational events — cash refills, cash retracts — and automatically associate commissions with their originating transaction. That meant modeling transaction *relationships* and business events, not just comparing values.
The platform automatically identified the customer account tied to a given transaction, which turned "transaction X failed reconciliation" into "which customer and account were affected, and what should happen next" — a much more actionable output for the operations team.
This project changed how I think about backend engineering. At smaller scale, a system is a collection of endpoints, tables, and business logic. At financial transaction volume, that model isn't sufficient — the questions that matter shift to how data moves through the system, how you guarantee a transaction is processed exactly once, how you trace it months later, and how you keep the system adaptable as external formats and volume both keep changing.
Good architecture here wasn't just about making the system work — it was about making sure it kept working as volume, integrations, and the cost of failure all increased. That's the lens I still bring to large-scale transaction-processing systems today.
Feel free to email me at hi@riteshr.com.np for counsuting work, and I'll get back to you.