• Olatunde Success portraitOlatunde Success
  • Date:  14 July 2026
  • NestJS

One NestJS Monorepo, Three Fintech Products: How I Structure Dbrij, Cirva, and Resikonet

Olatunde Success walks through the NestJS monorepo architecture powering three production fintech products at SAW Technologies: module boundaries, shared domain libraries, per-product deployments, and the rules that keep one codebase from becoming one big ball of mud.

At SAW Technologies, one NestJS monorepo powers Dbrij, Cirva, and Resikonet. Three products, one repository, one CI pipeline, and a small team that has to move fast without breaking money movement. This setup gets questioned in every architecture conversation I have, so here is exactly how it works and why I keep choosing it.

What lives where
  • apps/ holds one deployable NestJS application per product, plus workers. Each app owns its controllers, its wiring, and nothing else.

  • libs/domain holds the business logic: wallets, escrow, ledger, KYC, notifications. This is where the real code lives.

  • libs/infra holds the boring shared pieces: Prisma clients, BullMQ setup, the encryption module, audit logging, idempotency middleware.

  • Each product composes domain libraries like ingredients. Cirva imports wallets and KYC; Resikonet imports escrow and disputes; Dbrij imports nearly everything.

The rules that keep it sane

A monorepo without boundaries becomes one application wearing three costumes. Our rules are mechanical enough to enforce in review. Apps may import libs; libs may never import apps. Domain libraries may not import each other sideways without an explicit interface. And every money-touching library gets its own test suite that runs even when only another product changed, because shared code means shared blast radius.

Why not three repositories?

Because the most valuable code we own is the code all three products share. The AES-256-GCM field encryption module, the idempotency layer, the audit logger, the SafeHaven and Paystack integrations: these were hardened once and reused everywhere. In separate repositories they would have drifted into three slightly different, slightly wrong versions. In the monorepo, a security fix lands everywhere in one pull request.

Deployment stays separate

Sharing code does not mean sharing fate at runtime. Each product builds its own container and deploys on its own schedule. A Resikonet release cannot take Cirva down. The monorepo is a development-time decision, not a runtime one, and keeping those two ideas separate is most of the trick.

Share the code that must never diverge. Isolate the deployments that must never fail together. That is the entire philosophy.

More from the blog

Want to talk about this article or a project?

© 2026 Olatunde Success. All rights reserved.

Built in Ibadan, Nigeria

background