System Case Study / 01

ONDC Financial
Services Connector.

Role

Sole Full-Stack Architect

Context

Confidential Fintech (NDA)

Type

Zero-to-One Build

Status

๐ŸŸข Personal Loan Live

/ Overview

Sole architect of a live ONDC BAP/BPP financial connector โ€” built from zero when ONDC had almost no developer documentation.

I owned the ONDC integration entirely โ€” no team, no existing codebase, no tutorials. Built the full Personal Loan BAP/BPP flow from the raw Beckn Protocol spec, reverse-engineering every payload from live network logs. Purchase Finance and Working Capital connectors are built on the same infrastructure and going live next.

Also contributed to the broader fintech platform โ€” including the MF dashboard and RTA pipeline โ€” but the ONDC connector is the work I designed and shipped independently end to end.

/ What Was Built

Not one product โ€” an entire financial ecosystem. Three live credit products, two external network integrations, and an automated data pipeline.

01

ONDC Personal Loan

  • โ€” Full BAP/BPP connector โ€” sole architect
  • โ€” End-to-end loan application lifecycle
  • โ€” Beckn Protocol state machine from scratch
  • โ€” Onboarded 2 Credit Providers โ€” Live โœ…
02

ONDC Purchase Finance & Working Capital

  • โ€” Purchase Finance โ€” embedded checkout flow
  • โ€” Working Capital โ€” business lending product
  • โ€” Both built on same BAP/BPP connector
  • โ€” Integration complete โ€” going live soon
03

Mutual Fund Platform

  • โ€” Multi-MFD tenant dashboard โ€” Next.js
  • โ€” BSE Star MF integration (team effort)
  • โ€” CAMS & Karvy RTA mailback pipeline
  • โ€” UIDAI Aadhaar face KYC integration

/ Architecture

A polyglot stack chosen deliberately โ€” each language doing what it does best.

ONDC Beckn Gateway
BSE Star MF Network
CAMS / Karvy RTA Email
Webhooks / API Calls / Email Ingestion
โ†“ ย ย ย ย ย ย ย ย ย ย ย  โ†“ ย ย ย ย ย ย ย ย ย ย ย  โ†“

Primary Gateway

Node.js / Express

Idempotency ยท Auth ยท Routing

Data Pipeline

FastAPI / Python

RTA Parsing ยท Reconciliation

โ†“ ACID Writes ย ย ย ย ย  โ†“ Structured Logs

Financial Ledger

PostgreSQL

ACID ยท Row Locks

Webhook Sink

MongoDB

Payloads ยท Logs

Idempotency

Redis

Cache ยท Dedup

Frontend

Next.js (SSR)

Multi-tenant dashboards with Server-Side Rendering for fast initial loads. Complex state machines for dynamic KYC flows, loan offer screens, and real-time application tracking across multiple tenants without data bleed.

API Gateway

Node.js + Express

High-concurrency gateway handling the full volume of asynchronous ONDC webhooks, non-blocking network calls, and real-time updates. Chosen specifically for its event-loop architecture suited to I/O-heavy webhook processing.

Data Processing

Python + FastAPI

Isolated into a separate microservice for mailback parsing. Ingests raw CAMS and Karvy RTA emails, parses messy unstructured data, transforms it into structured portfolio records, and pushes to the core ledger โ€” all async.

Database Strategy

PostgreSQL + MongoDB + Redis

PostgreSQL for all financial state โ€” strict ACID compliance for loan disbursals and SIP transactions. MongoDB as a high-throughput sink for raw webhook payloads. Redis for idempotency keys and deduplication of duplicate webhook fires.

/ Hardest Problem

Race conditions in financial state machines. Duplicate webhook fires leading to double disbursals.

The Problem

The ONDC gateway fires webhooks for every state change in a loan application. Under load, the same webhook fires twice within milliseconds โ€” both arrive at the Node.js server simultaneously. A naive backend processes both, creating duplicate ledger entries and double disbursals. In financial systems this is catastrophic.

Solution 01

Idempotency Middleware

Every incoming webhook is hashed into a unique idempotency key based on the transaction ID, state, and timestamp. Before processing, the Node.js gateway checks Redis for this key. If it exists โ€” the request already processed successfully โ€” we return the cached response immediately without touching PostgreSQL. The duplicate is handled in under 1ms with zero database load.

Solution 02

PostgreSQL Row-Level Locks

For any operation mutating loan state or disbursing funds, I wrap the entire operation in a PostgreSQL transaction with SELECT ... FOR UPDATE. If two threads race to approve the same loan, the database forces them to queue. The second thread reads the already-updated state and exits cleanly. No duplicate disbursal is possible at the database level โ€” even if the application layer fails.

/ What I Learned

01

Building without documentation is a skill

ONDC had almost no developer resources when we started. I reverse-engineered the entire Beckn Protocol flow from the spec PDF and live network payloads. This taught me to read protocol specs directly rather than waiting for tutorials.

02

Financial systems need defence in depth

One layer of protection is never enough. I implemented idempotency at the API layer, row locks at the database layer, and state machine validation at the business logic layer. Any two of these would survive individually if one failed.

03

Polyglot is sometimes the right answer

Using Python for the RTA mailback pipeline while Node.js handled the real-time API was the right call. Forcing everything into Node.js would have made the data parsing significantly harder. Pick the right tool per problem.