Forge64 logo
All app types

Build a ledger app

How to build a ledger app with AI

To build a ledger app, describe who it is for and what they do in it, and let Forge64 plan and generate the app. A money app built on a double-entry ledger: immutable balanced journal entries in integer minor units, accounts/wallets with holds, idempotent transfers via a saga over the payment rail (Forge Payments), reconciliation against the processor, statements, an append-only audit trail, and per-user limits and velocity checks that fail closed. The core parts of a first version are double-entry ledger, money representation, accounts and wallets, holds and authorisations and idempotency layer.

Last checked

What the first version needs

These are the parts a ledger app needs before it is useful. Each one is something the plan covers.

  • Double-entry ledger: The system of record: every movement of value is a balanced journal entry; balances are derived from, and checked against, the journal.
  • Money representation: Exact arithmetic with no float rounding and no currency mixing.
  • Accounts and wallets: Model each user wallet, system account and external clearing account with a type and normal side.
  • Holds and authorisations: Reserve funds for pending actions (card auth, pending payout) without moving them.
  • Idempotency layer: Make every money-moving API safe to retry exactly once in effect.
  • Transfers saga: Internal transfers are one atomic entry; transfers involving the processor are a recoverable multi-step saga.
  • Funding and payout rail: Move real money in and out via a licensed partner.
  • Reconciliation: Prove daily that the ledger agrees with the processor and with itself.
  • Limits and velocity controls: Cap how much and how fast each user can move money, failing closed.

Parts you can add in the first version

  • Operations console: Review reconciliation breaks, freezes, manual adjustments (with four-eyes), disputes.

The data it stores

Each table below becomes part of the Postgres database that belongs to your app.

  • ledger_accounts: kind: asset|liability|equity|income|expense; status: active|frozen|closed; balance_minor is a cache maintained only by post_entry under a row lock and verified hourly against journal_lines; CHECK (balance_minor >= 0 OR allow_negative); never edited by application code outside post_entry.
  • journal_entries: immutable header of a transaction; kind: deposit|withdrawal|transfer|fee|adjustment|reversal; reversal entries point to the original and swap sides; INSERT only, UPDATE and DELETE are rejected by trigger and revoked from the app role.
  • journal_lines: direction D|C, CHECK (amount_minor > 0), currency must equal the account currency (trigger); a deferred constraint trigger enforces sum(D) = sum(C) per entry and currency at COMMIT; immutable like the header.
  • holds: status: active|captured|released|expired; hold amount may be captured partially only if the product allows it; holds count against available balance but are not journal entries.
  • idempotency_keys: status: in_progress|done; same key with a different request_hash returns 422; the stored response is returned verbatim on replay.
  • transfers: status: pending|held|submitted|settled|failed|reversed; step records the last durable saga step so the job can resume; money only moves via the journal, this row is workflow state.
  • processor_events: raw signed provider events stored before processing; processing posts ledger entries idempotently keyed by event_id; PAN/CVC must never appear (card data never reaches Forge).
  • velocity_counters: window_kind: hour|day|month; incremented inside post_entry's transaction so limits are exact under concurrency.
  • user_limits: tier: unverified|basic|verified; defaults come from env ceilings; any raise requires an audit_log entry and, for verified, a kyc_verifications row (phase 2).

Pages and endpoints

Routes in a first version of a ledger app
RouteWho can use itWhat it does
/walletauthedbalances (available vs pending), recent activity with cursor pagination.
/wallet/sendauthedtransfer form with confirmation step, limits shown before submit.
/wallet/statementsauthedmonthly statements list and signed download.
/api/accountsauthedlist the caller's accounts with balance and available amounts.
/api/accounts/[id]/entriesauthedkeyset-paginated journal lines for one account; owner only.
/api/transfersauthedcreate a transfer; Idempotency-Key required; limits, KYC tier and balance checked in the posting transaction.
/api/depositsauthedcreate a processor payment intent for top-up; credited only on the verified webhook.
/api/withdrawalsauthedrequest a payout via Forge Payouts; places a hold, Idempotency-Key required.
/api/holds/[id]/captureinternalcapture or release a hold; callable only by server code paths.
/api/webhooks/payoutsinternalForge Payouts settlement and failure events; signature verified; idempotent by event id.
/admin/reconciliationinternalbreaks queue, resolve with adjusting entry and second approver.

What to leave out of version one

  • No floating point money, ever.
  • No custody of customer funds outside a licensed partner; the app is not a bank or money transmitter.
  • No editing or deleting of journal rows; corrections are reversing entries.
  • No cryptocurrency, trading or securities in phase 1.
  • No card issuing, FX or lending in phase 1.
  • Identity verification (KYC/AML): plan for it, build it later.
  • Card issuing and FX: plan for it, build it later.

How Forge64 builds it

Forge64 matches your description to one of 12 reference architectures, writes the plan and data model into the project, generates the app, and runs a quality gate over the code before you see it. Each app gets its own Postgres database and sign-in with no per-user fee. Hosting on Forge Cloud and Forge Payments are rolling out.

This is a reference design for the category, not a promise that every item is generated today. Built-ins such as email, background jobs, file uploads and search are coming soon, so anything here that needs them is something you add yourself for now.

FAQ

What does a ledger app need first?
Double-entry ledger, money representation, accounts and wallets, holds and authorisations, idempotency layer and transfers saga. The plan for a ledger app covers all of these before it generates code.
What should I leave out of the first version of a ledger app?
No floating point money, ever. No custody of customer funds outside a licensed partner; the app is not a bank or money transmitter. No editing or deleting of journal rows; corrections are reversing entries.
Which products define the ledger app category?
Well-known examples include Wise, Revolut, Square, Modern Treasury and TigerBeetle / Formance ledgers. Use them to decide which features your users expect, then describe your own version.

Build your app with Forge64

One prompt to a running app with auth, database, hosting and payments. Start free, no credit card required.

Start building for free