How to Build a Fintech MVP: Architecture, Ledger, Security, and Scalable Business Processes
How we approach fintech MVP development with Formance Ledger for financial correctness and Temporal for durable, scalable business processes.
Building a fintech MVP is fundamentally different from building a conventional SaaS product.
In a typical MVP, teams optimize primarily for speed: ship the smallest possible feature set, validate the market, collect feedback, and iterate. In fintech, speed still matters—but financial correctness, traceability, security, and operational resilience cannot simply be postponed until “after the MVP.”
A fintech product may start with only a few hundred users, but from the first transaction it must answer several critical questions:
- Where did the money come from?
- Where did it go?
- Why was the transaction created?
- Was the operation completed, rejected, reversed, or duplicated?
- Can the financial state be reconstructed during an audit?
- What happens if a service crashes halfway through a payment?
- Can the system safely scale without losing process consistency?
A successful fintech MVP is therefore not a disposable prototype. It is a focused first version built on a foundation that can evolve into a production-grade financial platform.
This article explains how we approach fintech MVP development, why we use Formance Ledger for strict financial control and auditability, and how Temporal helps us implement reliable business processes that can scale.
1. Start with the Financial Model, Not the User Interface
One of the most common mistakes in fintech development is starting with screens, APIs, or payment-provider integrations before defining the financial model.
Before writing production code, the team should describe the complete lifecycle of money inside the platform.
For every financial operation, define:
- Who owns the funds?
- Where are the funds currently held?
- Which accounts are affected?
- When does the balance become available?
- Can the transaction be reversed?
- Who pays fees?
- What happens if an external provider fails?
- Which state is considered financially final?
- What information must be retained for reconciliation and audit?
For example, a simple marketplace payment may involve significantly more than one transfer:
Customer payment
↓
Pending platform funds
↓
Available merchant balance
↓
Platform fee
↓
Merchant payout
↓
External bank settlement
Each transition must have a clear business meaning.
The technical architecture should reflect this financial lifecycle rather than hiding everything behind a single generic transactions table.
2. Define the MVP Scope Around One Complete Money Flow
A fintech MVP should not attempt to support every possible financial product.
Instead, it should implement one complete end-to-end flow extremely well.
Depending on the product, that flow may be:
- wallet funding and withdrawal;
- customer-to-customer transfer;
- card payment and refund;
- merchant payment and payout;
- subscription billing;
- invoice payment;
- currency conversion;
- lending disbursement and repayment;
- escrow funding and release.
The important requirement is completeness.
A partially implemented set of ten payment scenarios is usually less valuable than one reliable scenario that supports:
- authorization;
- validation;
- ledger posting;
- provider communication;
- status tracking;
- retries;
- failure handling;
- reconciliation;
- reversal;
- audit history.
This approach reduces initial development cost while testing the most important assumption: whether users are willing to trust and use the financial product.
3. Treat the Ledger as the Financial Source of Truth
A fintech platform should clearly separate its operational application data from its financial records.
The application database may contain:
- customer profiles;
- payment requests;
- invoices;
- product settings;
- UI preferences;
- compliance statuses;
- external provider identifiers.
The ledger should contain the authoritative representation of value movement.
It should answer questions such as:
- What is the current balance?
- Which transactions created that balance?
- Which funds are pending?
- Which funds are reserved?
- How much does the platform owe its customers?
- Which fees have been earned?
- Which transaction reversed an earlier operation?
Using a normal mutable balance column is dangerous:
UPDATE wallets
SET balance = balance - 100
WHERE user_id = 42;
This operation changes the current value but does not, by itself, provide a complete and trustworthy financial history.
A mature financial system should derive balances from structured money movements recorded in an append-oriented ledger.
4. Why We Use Formance Ledger
For fintech solutions, we use Formance Ledger as a dedicated financial accounting layer.
Formance Ledger is designed as a programmable accounting database for financial applications. It records balanced movements between accounts, supports multiple assets, provides concurrency controls, and maintains a tamper-evident transaction history.
This gives us a much stronger foundation than implementing financial bookkeeping from scratch in a conventional application database.
4.1 Balanced Money Movements
Every financial movement must have both a source and a destination.
Conceptually:
Source account → Destination account
For example:
customer:alice:available
→ merchant:store-123:pending
Or:
merchant:store-123:pending
→ merchant:store-123:available
The key invariant is simple:
Value cannot disappear from one account without appearing in another account.
This protects the platform from a large category of implementation errors.
4.2 Immutable and Auditable Transactions
Financial history should not be silently edited.
Corrections should be represented by additional financial operations, such as reversals or corrective bookings, rather than by rewriting the original transaction.
This gives the platform a clear audit trail:
Original payment
↓
Refund request
↓
Refund transaction
Instead of:
Original payment record modified manually
This distinction is essential for:
- internal investigations;
- customer support;
- dispute resolution;
- reconciliation;
- financial reporting;
- compliance reviews;
- external audits.
We can always explain how the current financial state was reached.
4.3 Atomic Financial Operations
Many financial actions affect more than two accounts.
For example, a marketplace payment might split funds among:
- the merchant;
- the platform;
- a tax account;
- a partner;
- a reserve account.
A simplified transaction may look like this:
customer:alice:available
→ merchant:123:pending 94.00 EUR
→ platform:fees 5.00 EUR
→ platform:reserve 1.00 EUR
These postings must succeed or fail as one operation.
Atomic ledger transactions prevent situations where the merchant receives funds but the platform fee is not recorded, or where only part of a split payment is applied.
4.4 Multi-Asset Support
Modern fintech products often work with multiple currencies or asset types.
Examples include:
USD/2
EUR/2
GBP/2
USDC/6
LOYALTY_POINTS/0
The precision is part of the asset definition. This avoids unsafe floating-point arithmetic and makes rounding behavior explicit.
Money should always be stored using integer-based minor units or another exact numeric representation:
10.50 EUR → 1050 EUR cents
Never:
const balance = 10.50;
Binary floating-point numbers are not appropriate for authoritative monetary calculations.
4.5 Programmable Financial Rules
Formance provides Numscript, a purpose-built language for expressing financial movements.
A simplified example could look like:
send [EUR/2 10000] (
source = @customer:alice:available
destination = @merchant:store-123:pending
)
This transaction represents a transfer of 100.00 EUR.
More complex scripts can implement:
- fee splitting;
- commissions;
- reserves;
- controlled overdrafts;
- percentage-based allocations;
- refunds;
- settlement movements;
- platform revenue recognition.
Moving these rules into an explicit financial layer makes them easier to review, test, and audit than financial logic distributed across controllers, SQL statements, and background jobs.
5. Separate Financial State from Business Process State
The ledger and the business workflow solve different problems.
The ledger answers:
What happened financially?
The workflow engine answers:
What should happen next?
Consider a withdrawal:
- Validate the user.
- Check compliance restrictions.
- Reserve funds.
- Create a payout with the provider.
- Wait for provider confirmation.
- Finalize the ledger transaction.
- Notify the user.
- Trigger reconciliation.
- Release or reverse the reservation if the payout fails.
The ledger should not be responsible for calling the payment provider, sending notifications, or scheduling retries.
Similarly, the workflow engine should not become the authoritative source for financial balances.
A robust fintech architecture uses both:
Temporal
Controls the business process
Formance Ledger
Controls the financial state
6. Why We Use Temporal for Fintech Business Processes
Financial workflows are rarely simple synchronous request-response operations.
A process may take:
- milliseconds;
- several minutes;
- multiple days;
- weeks in the case of disputes or compliance reviews.
It may depend on:
- payment providers;
- banks;
- KYC services;
- AML systems;
- internal approval;
- asynchronous webhooks;
- scheduled settlement windows.
We use Temporal to implement these long-running and failure-resistant business processes.
Temporal provides durable workflow execution. Workflow state and progress are persisted through event history, allowing an execution to recover after worker crashes, network failures, deployments, or infrastructure outages.
Instead of manually implementing process state through a collection of database flags, cron jobs, queues, and retry counters, we can describe the workflow as application code.
6.1 A Typical Withdrawal Workflow
A simplified Temporal workflow may look conceptually like this:
export async function withdrawalWorkflow(
input: WithdrawalInput,
): Promise<WithdrawalResult> {
await validateWithdrawal(input);
await runComplianceChecks(input);
await reserveFunds(input);
try {
const payout = await createProviderPayout(input);
await waitForPayoutConfirmation(payout.id);
await finalizeWithdrawal(input, payout);
await sendWithdrawalCompletedNotification(input);
return {
status: "completed",
providerReference: payout.id,
};
} catch (error) {
await releaseReservedFunds(input);
await sendWithdrawalFailedNotification(input);
throw error;
}
}
The real implementation would also include:
- timeouts;
- retry policies;
- idempotency keys;
- compensation logic;
- webhook correlation;
- manual-review signals;
- monitoring metadata;
- versioning.
The important point is that the entire business process is visible as one coherent workflow.
6.2 Durable Execution
Suppose the workflow has already:
- validated the customer;
- reserved the funds;
- submitted the payout.
Then the worker crashes before the final confirmation is received.
With a traditional background job, the team must determine:
- which steps already succeeded;
- which steps are safe to repeat;
- whether the provider request was duplicated;
- how to restore the process state.
Temporal records workflow progress in an event history and can replay the workflow to restore its state.
This is especially valuable for fintech operations, where repeating a completed external action may create duplicate payments.
6.3 Controlled Retries
External financial services fail.
Typical issues include:
- temporary provider downtime;
- API timeouts;
- rate limiting;
- DNS or network problems;
- delayed webhooks;
- temporary database unavailability.
Retries are necessary, but not all operations should be retried in the same way.
For example:
const retryPolicy = {
initialInterval: "1 second",
backoffCoefficient: 2,
maximumInterval: "1 minute",
maximumAttempts: 8,
};
The retry strategy should depend on the operation:
| Operation | Typical strategy |
|---|---|
| Fetch provider status | Retry automatically |
| Send notification | Retry automatically |
| Create payment | Retry only with idempotency protection |
| Compliance rejection | Do not retry automatically |
| Invalid bank details | Require user correction |
| Manual review | Wait for an operator signal |
Temporal allows retry behavior to be defined explicitly instead of being scattered across multiple services.
6.4 Long-Running Workflows
A workflow may wait for an external event without consuming a continuously active application thread.
Examples include:
Wait for bank webhook
Wait for KYC approval
Wait for manual compliance review
Wait for settlement window
Wait for user document upload
Wait for dispute resolution
This is useful for:
- payouts;
- onboarding;
- card issuance;
- chargebacks;
- settlement;
- loan applications;
- account closure;
- suspicious-activity reviews.
6.5 Horizontal Scaling
Temporal workers can be scaled horizontally.
Additional workers can be deployed when:
- transaction volume increases;
- a new geographic region is launched;
- more provider integrations are added;
- reconciliation workloads grow;
- compliance checks become more complex.
Different workloads can be isolated through separate task queues:
payments
payouts
compliance
reconciliation
notifications
reporting
This prevents a slow provider integration from blocking unrelated business operations.
7. Recommended Fintech MVP Architecture
A practical fintech MVP architecture may include the following components:

High-level fintech MVP architecture with Formance Ledger as the financial source of truth and Temporal as the workflow orchestration layer.
Open the architecture diagram in full resolution
Core responsibilities
Application API
Responsible for:
- request validation;
- authorization;
- API contracts;
- user-facing resources;
- starting workflows;
- retrieving aggregated status.
PostgreSQL
Responsible for:
- customer data;
- product configuration;
- payment intents;
- provider references;
- workflow references;
- compliance metadata;
- non-financial application state.
Formance Ledger
Responsible for:
- authoritative balances;
- money movements;
- reservations;
- pending and available funds;
- fees;
- reversals;
- financial transaction history.
Temporal
Responsible for:
- payment lifecycles;
- withdrawal processes;
- onboarding;
- retries;
- timeouts;
- provider communication;
- compensation;
- manual-review steps;
- reconciliation orchestration.
Event and analytics layer
Responsible for:
- product analytics;
- operational dashboards;
- reporting projections;
- notifications;
- fraud signals;
- downstream integrations.
Analytical systems should consume financial events or exported ledger data rather than becoming the authoritative source for balances.
8. Design an Explicit Chart of Accounts
A clear chart of accounts is one of the most important parts of the system.
A possible account structure might look like this:
users:{userId}:available
users:{userId}:pending
users:{userId}:reserved
merchants:{merchantId}:pending
merchants:{merchantId}:available
merchants:{merchantId}:reserved
platform:fees
platform:refunds
platform:chargebacks
platform:reserves
treasury:bank:primary
treasury:bank:settlement
treasury:payment-provider:{provider}
This makes the financial meaning of balances explicit.
For example:
merchants:123:pending
means funds belong economically to the merchant but are not yet available for withdrawal.
By contrast:
platform:fees
represents revenue earned by the platform according to the product’s accounting policy.
The chart of accounts should be reviewed by:
- software architects;
- product owners;
- finance specialists;
- accountants;
- compliance stakeholders.
This should happen before the system begins processing real money.
9. Implement Idempotency Everywhere
Distributed financial systems must assume that the same request can arrive more than once.
Duplicates may be caused by:
- user retries;
- mobile connectivity issues;
- API gateway retries;
- message redelivery;
- provider retries;
- repeated webhooks;
- workflow activity retries.
Every externally initiated financial operation should have an idempotency key.
For example:
POST /v1/payments
Idempotency-Key: pay_9d1d9e20-71e3-4b30-a6fd-1a43f1204723
The system should persist the relationship between:
Idempotency key
Business operation
Workflow ID
Ledger transaction reference
Provider request reference
A possible database constraint:
CREATE UNIQUE INDEX ux_payment_idempotency_key
ON payments(idempotency_key);
A provider request should also use a stable idempotency key whenever the provider supports it.
A safe financial operation should tolerate repeated delivery without repeating its financial effect.
10. Use a State Machine for User-Facing Statuses
Financial statuses should be explicit and controlled.
For example:
CREATED
↓
VALIDATING
↓
COMPLIANCE_REVIEW
↓
FUNDS_RESERVED
↓
SUBMITTED
↓
PROCESSING
↓
COMPLETED
Possible alternative paths:
VALIDATING → REJECTED
COMPLIANCE_REVIEW → MANUAL_REVIEW
FUNDS_RESERVED → CANCELLED
SUBMITTED → FAILED
PROCESSING → REVERSED
Do not allow arbitrary status updates such as:
UPDATE payments SET status = 'COMPLETED';
Each transition should be connected to a valid business event.
For example:
const allowedTransitions = {
CREATED: ["VALIDATING", "CANCELLED"],
VALIDATING: ["COMPLIANCE_REVIEW", "REJECTED"],
COMPLIANCE_REVIEW: ["FUNDS_RESERVED", "MANUAL_REVIEW", "REJECTED"],
FUNDS_RESERVED: ["SUBMITTED", "CANCELLED"],
SUBMITTED: ["PROCESSING", "FAILED"],
PROCESSING: ["COMPLETED", "FAILED", "REVERSED"],
};
Temporal manages the execution path, while the application database provides an efficient projection for APIs and the user interface.
The ledger remains the authority for financial balances and postings.
11. Design for Compensation, Not Distributed Rollback
A financial process frequently spans systems that cannot participate in one database transaction.
For example:
Application database
Formance Ledger
Payment provider
Banking partner
Notification service
A classic distributed ACID transaction across all of these systems is normally impractical.
Instead, fintech systems should use compensating actions.
Example:
1. Reserve funds
2. Submit payout
3. Provider rejects payout
4. Release reserved funds
5. Mark payout as failed
6. Notify the customer
The compensation does not erase history. It creates a new operation that restores the intended financial state.
A Temporal workflow can coordinate this sequence and ensure the correct compensation is executed when a later step fails.
12. Reconciliation Is a Core Feature
Integrating with a payment provider does not mean the internal state will always match the provider’s state.
Discrepancies occur because of:
- missing webhooks;
- delayed settlement;
- manual provider-side changes;
- rounding differences;
- provider outages;
- duplicate notifications;
- chargebacks;
- banking cut-off times.
A fintech MVP should include at least a basic reconciliation process.
A reconciliation workflow can:
- Download provider transactions.
- Match them with internal operations.
- Compare amounts, currencies, statuses, and references.
- Detect missing or duplicated records.
- Automatically resolve known cases.
- Open an operational incident for unresolved differences.
Example reconciliation result:
{
"providerReference": "psp_839201",
"internalPaymentId": "pay_12345",
"providerAmount": 12500,
"ledgerAmount": 12500,
"currency": "EUR",
"providerStatus": "SETTLED",
"internalStatus": "COMPLETED",
"result": "MATCHED"
}
Potential mismatch:
{
"providerReference": "psp_839202",
"internalPaymentId": null,
"providerAmount": 9900,
"currency": "EUR",
"providerStatus": "SETTLED",
"result": "MISSING_INTERNAL_TRANSACTION"
}
Reconciliation should be considered part of the financial product, not merely an administrative script.
13. Security Must Be Built into the MVP
A fintech MVP should follow a strong security baseline from the beginning.
Authentication
Use an established identity platform and support:
- secure password policies;
- email or phone verification;
- multi-factor authentication;
- session revocation;
- device and login monitoring;
- short-lived access tokens;
- refresh-token rotation.
Authorization
Implement fine-grained permissions:
customer
merchant_operator
merchant_admin
support_agent
compliance_officer
finance_operator
system_administrator
auditor
Access to financial operations should follow least-privilege principles.
A support agent may view a transaction but should not be able to create an arbitrary ledger adjustment.
Data protection
Use:
- TLS for all network communication;
- encryption at rest;
- a managed secrets system;
- key rotation;
- tokenization where appropriate;
- strict log-scrubbing policies;
- encrypted backups;
- separate production and non-production environments.
Sensitive values must never appear in application logs:
Card numbers
CVV values
Passwords
Access tokens
Identity documents
Private API keys
Full bank-account credentials
Administrative controls
High-risk operations may require:
- maker-checker approval;
- step-up authentication;
- reason codes;
- immutable administrative audit records;
- transaction limits;
- IP or device restrictions;
- manual review.
14. Compliance Depends on the Product and Jurisdiction
There is no universal compliance checklist for every fintech platform.
Requirements depend on:
- countries of operation;
- customer type;
- regulated activity;
- payment methods;
- currencies;
- custody model;
- transaction volume;
- licensing structure;
- banking and payment partners.
Common areas include:
- KYC;
- KYB;
- AML;
- sanctions screening;
- transaction monitoring;
- suspicious-activity review;
- data retention;
- privacy regulations;
- PCI DSS;
- consumer-protection requirements;
- financial reporting.
The system should keep compliance decisions separate from basic application logic.
For example:
type ComplianceDecision =
| { status: "approved" }
| { status: "rejected"; reasonCode: string }
| { status: "manual_review"; caseId: string };
A Temporal workflow can wait for manual review without losing the surrounding payment context.
Legal and compliance specialists should confirm the exact requirements before the product processes real customer funds.
15. Observability for a Fintech MVP
Basic infrastructure monitoring is not sufficient.
A fintech platform needs technical and business observability.
Technical metrics
Track:
API latency: p50, p95, p99
HTTP error rate
Database connection-pool usage
Temporal task-queue backlog
Workflow failure rate
Activity retry count
Ledger request latency
Provider API latency
Webhook processing delay
CPU, memory, disk, and network usage
Financial and business metrics
Track:
Payments created
Payments completed
Payments failed
Total payment volume
Payout success rate
Funds currently pending
Funds currently reserved
Refund volume
Chargeback volume
Provider mismatch count
Reconciliation exceptions
Manual-review queue size
Trace identifiers
Every financial operation should be traceable through the entire system.
A single payment may have:
Correlation ID
Payment ID
Temporal Workflow ID
Ledger transaction reference
Provider payment reference
Reconciliation reference
These identifiers should be searchable in logs and operational tools.
16. Testing Strategy
Fintech testing must verify more than HTTP responses.
Unit tests
Use unit tests for:
- fee calculations;
- rounding;
- eligibility rules;
- state transitions;
- limits;
- currency precision;
- compliance decisions.
Ledger invariant tests
Verify that:
- every movement balances;
- prohibited overdrafts are rejected;
- unavailable funds cannot be spent;
- refunds do not exceed captured amounts;
- fees are posted correctly;
- reversals point to the original operation.
Workflow tests
Verify:
- retries;
- activity failures;
- workflow timeouts;
- duplicate signals;
- provider delays;
- cancellation;
- compensation;
- worker restarts;
- manual-review paths.
Integration tests
Run real integrations against sandbox environments for:
- payment providers;
- KYC services;
- email or SMS services;
- ledger;
- workflow infrastructure.
Failure-injection tests
Deliberately test cases such as:
The provider succeeds but the response is lost.
The webhook is delivered five times.
The worker restarts after funds are reserved.
The database is temporarily unavailable.
The provider status changes after a timeout.
The notification fails after the payment completes.
A financial system is defined as much by its failure behavior as by its successful behavior.
17. A Practical MVP Delivery Roadmap
Phase 1: Product and financial design
Define:
- target users;
- primary financial flow;
- legal model;
- supported currencies;
- transaction limits;
- provider responsibilities;
- chart of accounts;
- status model;
- audit requirements.
Phase 2: Foundation
Implement:
- authentication;
- authorization;
- customer model;
- environment separation;
- secrets management;
- CI/CD;
- infrastructure as code;
- observability baseline.
Phase 3: Financial core
Implement:
- Formance Ledger integration;
- account structure;
- deposits or funding;
- reservations;
- transfers;
- fees;
- reversals;
- idempotency.
Phase 4: Durable processes
Implement Temporal workflows for:
- payment processing;
- withdrawals;
- onboarding;
- compliance checks;
- provider retries;
- webhook handling;
- compensation.
Phase 5: Operations
Implement:
- reconciliation;
- support tools;
- manual review;
- audit views;
- dashboards;
- incident alerts;
- controlled financial adjustments.
Phase 6: Controlled launch
Launch with:
- limited users;
- limited transaction amounts;
- one currency;
- one provider;
- manual operational supervision;
- daily reconciliation;
- clearly defined incident procedures.
Expand only after the primary money flow is proven reliable.
18. What Not to Overbuild
A fintech MVP does not necessarily need:
- dozens of microservices;
- multi-region active-active deployment;
- a custom KYC engine;
- a custom fraud-detection platform;
- support for every currency;
- several payment providers;
- a complex event-streaming platform;
- a data lake;
- full automation of every operational process.
However, it should not compromise on:
- financial invariants;
- ledger integrity;
- idempotency;
- auditability;
- access control;
- recovery from failures;
- reconciliation;
- transaction traceability.
The objective is not maximum architectural complexity.
The objective is a small, understandable system that processes money correctly.
19. The Architectural Principle We Follow
Our fintech architecture is based on a clear separation of concerns:
Formance Ledger protects financial correctness.
Temporal protects business-process continuity.
PostgreSQL stores product and operational state.
External providers execute regulated or network-level operations.
Analytics systems provide reporting and insights.
This separation gives us several important advantages:
- financial balances are not derived from mutable business records;
- workflows survive application and infrastructure failures;
- external-provider retries are controlled;
- compensation logic is explicit;
- every money movement remains auditable;
- services can be scaled independently;
- new providers can be added without redesigning the accounting core;
- operational teams can understand where each process stopped.
Conclusion
Building a fintech MVP is not about implementing a few payment APIs as quickly as possible.
It is about creating the smallest viable financial system that can:
- move money correctly;
- explain every balance;
- survive partial failures;
- prevent duplicate operations;
- support audit and reconciliation;
- protect customer data;
- evolve as transaction volume grows.
We use Formance Ledger to provide strict control over financial movements, immutable transaction history, precise balances, and a strong audit foundation.
We use Temporal to implement durable, scalable business processes that continue correctly across retries, outages, delayed provider responses, manual reviews, and long-running financial operations.
Together, these technologies allow us to build fintech MVPs quickly without turning the first version into an unsafe or disposable prototype.
The result is not merely an MVP that demonstrates a user interface.
It is the first production-capable version of a financial platform.
Building a fintech MVP?
We help startups design ledger-backed architecture, durable payment workflows, and a production-ready first release — without hiring a full in-house team.