Skip to content
lazy devs
5 min readLazy Devs

How to build a fintech app

A founder's honest guide to building a fintech app: the MVP, the money plumbing that breaks, the stack we'd pick, and rough costs and timelines.

Most fintech demos look great. A clean dashboard, a balance, a transfer button. Then real money flows through it, a webhook fires twice, a refund lands before the charge it reverses, and you discover the demo was the easy 20%. The other 80% is plumbing nobody sees until it leaks. This guide is for the founder writing the checks, and it covers what a fintech app actually is, what to build first, and where the hard parts hide.

What it is and who it is for

"Fintech app" covers a huge range, from a budgeting tool that reads bank data to a product that holds and moves customer money. The deciding question is not technical, it is regulatory: do you ever touch funds yourself?

If you do, you are likely in money-transmission or e-money territory, which means licensing, capital requirements, and a compliance officer on payroll. Almost every startup avoids that by sitting on top of a regulated partner: a Banking-as-a-Service provider, an e-money institution, or a processor that handles custody for you. You build the experience, they hold the money and own the hard part of the license.

Write this decision down before anything else, because it sets your timeline, your budget, and your stack. A read-only product (account aggregation, analytics, lending decisions) ships in months. The moment you custody balances, add quarters and a legal budget.

The MVP feature set: first vs later

The temptation is to build the whole bank. Don't. A first version that proves people will move money through you needs less than you think.

Build first:

  • Onboarding with identity verification (KYC) wired to a provider, not hand-rolled.
  • Account linking or a funding source, through your banking or payments partner.
  • One core money movement (a payment, a transfer, a deposit) done correctly end to end.
  • A double-entry ledger recording every cent.
  • Authentication with step-up for sensitive actions.
  • An immutable audit trail.
  • Reconciliation against your provider, even if it is a daily script at first.

Leave for later:

  • Multi-currency and FX.
  • Cards and physical issuance.
  • In-house fraud scoring (rules plus a vendor are plenty early on).
  • Rich analytics dashboards.
  • A mobile app, unless your wedge genuinely needs one. (PWA vs native is worth a hard look before you commit.)

The honest MVP is one money path that never loses a cent, fully auditable, sitting on a partner who holds the funds. Everything else is a feature, not a foundation.

The hard parts most teams underestimate

Money is not a float. 0.1 + 0.2 does not equal 0.3 in JavaScript, and that rounding error becomes a reconciliation nightmare. Store amounts as integers in the smallest unit (cents, pence) plus an explicit currency code, and wrap them in a type so you can't accidentally add USD to EUR.

You need a ledger, not a balance column. Never update a balance in place. Record immutable debits and credits, then derive the balance by summing them. This is double-entry bookkeeping, it is 600 years old, and it works. Every movement is two rows that must net to zero:

create table ledger_entries (
  id           bigint generated always as identity primary key,
  txn_id       uuid        not null,          -- groups the two legs
  account_id   bigint      not null,
  direction    text        not null check (direction in ('debit','credit')),
  amount       bigint      not null check (amount > 0),  -- minor units
  currency     char(3)     not null,
  created_at   timestamptz not null default now()
);
 
-- the two legs of a $5.00 transfer must sum to zero per txn
-- enforce in a trigger or a tested service-layer invariant
create index on ledger_entries (account_id, created_at);
create index on ledger_entries (txn_id);

The entries are append-only. A balance is a sum(), optionally cached. A bug becomes traceable instead of a guess.

Idempotency is not optional. Webhooks and payment events arrive out of order, twice, or not at all. If a retried event runs your charge logic again, you double-charge a customer, and that is the kind of bug that ends up on social media. Every money operation needs an idempotency key, stored, so a replay is a no-op:

async function transfer(key: string, from: bigint, to: bigint, amount: bigint) {
  // INSERT ... ON CONFLICT DO NOTHING: the key is the gate
  const fresh = await db.insertIdempotencyKey(key);
  if (!fresh) return db.getResult(key); // already processed, return prior result
 
  const result = await db.postLedgerTransfer(from, to, amount); // two legs, one txn
  await db.saveResult(key, result);
  return result;
}

Reconciliation is where the bugs live. Your numbers and your provider's numbers drift, and you find out at month-end if you are lucky and at audit if you are not. Build a job that compares them daily and alerts on any gap. Nobody watches background jobs on a Tuesday night, which is exactly why they fail there.

The audit trail is a feature, not a log. You need to answer "who did what, to which account, when, and why" months later, including actions by your own staff and support tools. Keep it append-only, timestamped, and separate from operational data. Retrofitting it means reconstructing history you no longer have.

The stack we would reach for and why

No surprises here, and that is the point. Fintech rewards boring, proven tools.

  • Postgres for the data, because a relational database with real transactions is exactly what a ledger needs. numeric and bigint, never float.
  • Node and TypeScript, with money modelled as a branded type so the compiler catches currency mix-ups. Strict mode, no exceptions.
  • Next.js for the app, with the sensitive logic behind server-side API and backend engineering rather than in the browser.
  • A regulated partner for custody, plus a Stripe integration or banking provider for the actual money rails. PCI scope drops to near zero if card data never touches your servers (use hosted fields).
  • A KYC vendor (Persona, Onfido, Alloy) for identity and watchlist checks. You buy this, you never build it.
  • A vetted auth provider with step-up authentication, so moving money is a higher bar than logging in.

The theme is least privilege everywhere: every request checks ownership (the most common fintech breach is user A reading user B's data by changing an ID), secrets live in a manager not in env files committed by accident, and staff access is scoped and logged.

Rough timeline and cost (clearly rough)

Treat these as order-of-magnitude, not quotes. Every project differs.

  • Read-only or decisioning product (no funds held): roughly 3 to 5 months with a small senior team.
  • Product that moves money via a partner: roughly 6 to 12 months, much of it on integration, reconciliation, and compliance rather than the UI everyone gets excited about.
  • Ongoing compliance (SOC 2, monitoring, audits): a recurring cost in the low five figures a year and up, not a one-time line.

The pattern: the visible app is usually the smaller half. An agency that only quotes you the screens has not priced the hard part.

What to watch out for

  • "We'll add compliance later" almost always costs more than building it in. SOC 2 Type II needs an observation window of several months, so start the clock early if you sell to businesses.
  • A clumsy KYC flow kills conversion faster than almost anything. Budget UX attention there, not just money.
  • Don't build a machine-learning fraud engine for your first thousand users. You lack the data to train it and have better things to do.
  • Pretty dashboards demo well and get overweighted. The ledger underneath is what actually matters.
  • Test the unhappy paths: failed payments, partial refunds, reversed transfers, duplicate webhooks. That is where real money goes missing.

The takeaway

Get four things right early and the rest gets easier: store money as integers in a ledger, make every operation idempotent, keep an immutable audit trail, and check authorization on every request. Decide your compliance scope before you build, not after a customer asks for your SOC 2 report.

This is squarely the kind of thing we build and the kind of thing we get called in to fix. If you want a second pair of eyes on the architecture before you commit to it, let's talk.

Related service

API & Backend Engineering

Secure, well-documented APIs that scale.

Learn more

Want this built right?

This is the work we do every day. Tell us what you are building and we will show you exactly how we would ship it.

hello@lazydevsagency.com