Frappe keeps coming up in fintech dev threads because it’s fast to prototype with, open-source, and comes with a built-in framework (plus Frappe/ERPNext ecosystem) that can shortcut a lot of backend boilerplate. But “fast to build” and “ready for banking-grade compliance” are two different bars. Here’s where Frappe actually fits in banking app development, and where it needs serious reinforcement before it touches real money.
What is Frappe, and why does it come up for banking apps?
Frappe is an open-source, Python-based full-stack framework (the same engine behind ERPNext) with built-in ORM, role-based permissions, REST APIs, and a low-code app builder. Teams gravitate to it for banking-adjacent tools because it speeds up admin panels, internal dashboards, and workflow-heavy backends.
What is Frappe actually good for in a banking context?
-
Internal admin/ops dashboards (loan processing queues, KYC review panels, transaction monitoring UIs)
-
Rapid MVP backends for lending, BNPL, or internal fintech tools
-
Role-based access control out of the box, useful for compliance-adjacent permission structures
-
Custom reporting and workflow automation without building from scratch
Where does Frappe fall short for customer-facing banking apps?
-
No built-in PCI-DSS-grade payment handling - you’re still integrating third-party processors (Stripe, Braintree, etc.) and hardening the stack yourself
-
Not designed natively for high-throughput, real-time transaction processing at neobank scale
-
Security hardening, encryption-at-rest, and audit logging need to be added, not assumed
-
Mobile-first UX (the actual customer-facing app) usually needs a separate native/cross-platform layer Frappe isn’t a mobile app framework
So should you build your banking app on Frappe?
Frappe is a solid choice for the internal/admin backend layer of a fintech product, especially early on. It’s a weaker choice as the core system of record for a customer-facing, regulated banking app without significant custom security and compliance work layered on top.
At**Nimble AppGenie** we’ve evaluated frameworks like this across 350+ fintech and banking builds, and the pattern holds: pick the framework that gets your ops team moving fast, but never let that decision quietly become your compliance architecture.
Has anyone here actually taken Frappe past MVP into a licensed banking product? Curious what compliance gaps you hit first.
Hi @nimbleappgenie
Just curious - Is it true that most banks prefer postgresql and is this a dealbreaker?
Thanks
@asieftejani may be but what i know most of them prefer relational databases for transactions that too specifically they mentioned as postgresql. I connected with 2-3 banks operated in India, they are using postgresql.
1 Like
As you have discovered, Frappe as back-office glue, rest api integrations, onboarding state mapping, is great!
What works ootb:
- Social Login
- Auth Hooks for global OIDC or custom auth
- Connected App for OIDC integrations with per-user authorization.
What you need to ensure:
- keep the ERPNext and core frappe under the vpn. Only expose
/api/method/your_app.gateway.* from your load balancer. Rest keep under VPN, even /api/resource/*. This will pass audits easier than you exposing complete frappe with desk.
- Keep the operations ledger external in high-throughput system and sync only aggregated entry instead of 1:1 transactions. E.g. your accountants will get Daily balances in morning. Drill-down happens from other service.
- Use hacked python reports from frappe to connect to analytics database to show filtered drill-down if needed.
As I was building the high-throughput ledger api, I realised it is a cross-cutting concern for lot of cases other than finance and stock. E.g. Crypto wallets, loyalty points, API rate-limits, Carbon credits, etc. I extracted it out as lib-ledger-core. It is an async lib that allows you to connect to any SQL database engine that is supported by SQLAlchemy for normal cases. For hyperscale cases use Tigerbeetle as ledger adapter and KurrentDB as event store. Use it in your python app to build ledgers.
In brief,
# example.py
import asyncio
from decimal import Decimal
from ledger_core.migrations import run_migrations
from sqlalchemy.ext.asyncio import create_async_engine
from ledger_core.adapters.sqlalchemy import SqlAlchemyEventStore, SqlAlchemyLedger
from ledger_core.models import TransferCommand
from sqlalchemy.ext.asyncio import create_async_engine
async def main():
engine = create_async_engine("sqlite+aiosqlite:///:memory:", future=True)
# Run migrations
await run_migrations(engine)
# Instantiate Adapters
ledger = SqlAlchemyLedger(engine)
event_store = SqlAlchemyEventStore(engine)
# Seed an account with initial funds
await ledger.seed_account(tenant_id="tenant_1", account="CASH", amount=Decimal("1000.00"))
# Execute a Transfer
cmd = TransferCommand(
tenant_id="tenant_1",
debit_account="EQUIPMENT",
credit_account="CASH",
amount=Decimal("250.00"),
reference="INV-2026-001",
description="Purchased office equipment",
)
transfer_id = await ledger.transfer(cmd)
print(f"Executed Transfer ID: {transfer_id}")
# Record Domain Event
await event_store.append(
tenant_id="tenant_1",
stream_id="equipment-purchases",
events=[
{
"type": "EquipmentPurchased",
"transfer_id": transfer_id,
"amount": "250.00",
}
],
expected_version=0,
)
# Check Balances
cash_bal = await ledger.get_balance("tenant_1", "CASH")
equipment_bal = await ledger.get_balance("tenant_1", "EQUIPMENT")
print(f"CASH Balance: {cash_bal}") # Outputs: 750.00
print(f"EQUIPMENT Balance: {equipment_bal}") # Outputs: 250.00
await ledger.close()
await event_store.close()
if __name__ == "__main__":
asyncio.run(main())
once example.py is ready execute:
uv venv
source ./.venv/bin/activate
uv pip install lib-ledger-core aiosqlite
uv run python example.py
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 001_baseline, Baseline schema for ledger-core.
Executed Transfer ID: e86ad402-b6fa-4826-b172-815cd1d6f41f
CASH Balance: 750.000000
EQUIPMENT Balance: 250.000000
1 Like