Financial software is unforgiving in a specific way: the failure modes are silent.
A rendering bug is obvious, because someone sees it and reports it. A rounding error in a settlement calculation is not. It produces a number that looks entirely plausible, and by the time anyone notices, it has been quietly wrong for months across hundreds of thousands of transactions. Correcting it means reconstructing what every affected balance should have been, which is considerably more expensive than the original bug.
That asymmetry shapes every engineering decision we make in this sector.
What we build
- Payment orchestration. Routing across multiple providers, retry and fallback logic, reconciliation against provider settlement files, and the operational tooling to investigate a payment that did not behave as expected.
- Ledgers and balances. Double-entry accounting engines where the invariant is that the books balance, enforced by the system rather than by convention.
- Onboarding and KYC. Identity verification workflows integrating document checks, sanctions and PEP screening, with the audit trail regulators expect and the ability to re-run a decision as rules change.
- Regulatory reporting. Scheduled extracts in prescribed formats, with the data lineage to demonstrate how each figure was derived.
- Back-office operations. What operations teams need in order to investigate a transaction, issue a refund, place a hold or correct an error, with role-based permissions and four-eyes approval on anything that moves money.
The engineering decisions that matter
Money is never a float
Amounts are integer minor units with an explicit currency: 4999 and "EUR", never 49.99.
Binary floating point cannot represent most decimal fractions exactly. The error is invisible in any single calculation and accumulates across a settlement run. This is not a theoretical concern. It is the single most common source of the silent discrepancies that turn up during reconciliation, and it is trivially avoidable by choosing the right type on day one.
Currency belongs alongside the amount, not in a column somewhere else. A bare integer with an implied currency is an outage waiting for your first multi-currency customer.
Idempotency is designed in, not retrofitted
Payment endpoints get called twice as a matter of routine: client timeouts, user double-taps, load balancer retries, provider webhook redelivery. Each duplicate is legitimate, and exactly one should move money.
The answer is a client-supplied idempotency key, stored with the full response, where a database unique constraint enforces exactly-once rather than application logic. The check-then-act pattern that looks correct in review is a race, and it fails only under the concurrency of production.
The case that most implementations miss is the duplicate arriving while the original is still running, which is also the most common case, since the duplicate is usually caused by the original being slow.
Everything is auditable
Financial records are corrected by appending, never by overwriting. An append-only event log plus immutable transaction records means you can reconstruct the state of any account at any past point in time. That is what regulators ask for, and what you need yourself the first time a customer disputes a balance.
Storing only the current state is cheaper right up until the moment someone asks how it got there.
Reconciliation is a feature, not a script
If the system cannot prove daily that its view of the world matches the provider’s, differences accumulate silently. Reconciliation belongs in the product: an automated daily comparison against provider settlement files, with a defined workflow for the exceptions it finds and a person accountable for clearing them.
Building this at the start is what stops small discrepancies becoming a multi-month investigation.
Failure paths get the same attention as success paths
Payments fail partially. A provider times out and you do not know whether the charge landed. A refund succeeds on the provider side and fails to record locally. These are not edge cases. At volume they are daily events.
Every mutating operation needs a defined recovery path, and anything that cannot be resolved automatically needs to surface as an actionable item in a queue a human can work. Silent failure is the one outcome that is never acceptable.
Compliance, realistically
We are a software engineering partner, not your compliance advisor. What we do is build so that satisfying your advisor is straightforward rather than a retrofit.
In practice that means a few things. PCI-DSS scope reduction, most often by ensuring card data never touches your infrastructure at all, using provider-hosted fields or tokenisation, so the compliance burden stays where it belongs. PSD2 and strong customer authentication, including the exemption logic and the fallback when a challenge fails. GDPR obligations around personal and financial data, where the tension between the right to erasure and regulatory retention requirements needs deciding deliberately rather than discovered late. Audit trails detailed enough that a regulator’s question is answered with a query.
Integration is most of the work
Fintech systems are rarely self-contained. A typical platform talks to payment providers, card processors, banking partners, identity and document verification services, sanctions screening, accounting systems and at least one regulatory reporting endpoint.
Each has its own model, its own failure behaviour and its own idea of what a transaction is. The integration layer is where that inconsistency gets normalised into something the rest of the system can reason about, and it is where most of the real engineering effort in a fintech build actually goes.
Treating integrations as configurable adapters rather than as hard-coded assumptions is what makes it possible to add a second provider without rewriting the first.
What we would ask you first
Before proposing anything, we would want to understand: which regulatory regimes you operate under and which you intend to enter; whether you hold funds or move them; what your reconciliation process looks like today and who owns it; where card data currently flows; and what happens operationally right now when a payment goes wrong.
The answers determine the architecture far more than the technology preferences do.