Why Nivo?

Building a neobank is hard. Building one right is harder. This is the story of how Nivo came to be.


The Problem with Portfolio Projects

Most portfolio projects fall into one of two traps:

  1. Too simple — CRUD apps that don’t demonstrate real engineering skill
  2. Too ambitious — Half-finished projects that promise everything, deliver nothing

Nivo takes a different approach: scope small, execute deep.

Instead of building a complete bank (impossible), we built the core systems that make a bank work — and built them well.


What Makes Nivo Different

Real Domain Complexity

Fintech isn’t just moving numbers around. It’s about:

  • Money integrity — Ensuring ₹1,000 can never become ₹1,001 or ₹999
  • Audit trails — Every rupee must be traceable to its source
  • Compliance — KYC, transaction limits, fraud detection
  • Concurrency — Multiple transfers happening simultaneously without race conditions

Nivo implements all of these. Not as stubs or TODOs — as working systems.

Production Patterns, Not Tutorials

graph TB
    subgraph "What Most Tutorials Teach"
        A[Single Service] --> B[Single Database]
        B --> C[CRUD Operations]
    end

    subgraph "What Nivo Demonstrates"
        D[API Gateway] --> E[Identity Service]
        D --> F[Wallet Service]
        D --> G[Transaction Service]
        D --> H[Ledger Service]
        D --> I[Risk Service]
        D --> J[RBAC Service]

        E --> K[(PostgreSQL)]
        F --> K
        G --> K
        H --> K
        I --> K
        J --> K

        G --> L{SSE Broker}
        L --> M[Real-time Updates]
    end

Nivo demonstrates patterns you’d actually use in production:

Pattern Implementation
Double-Entry Ledger Every transaction creates balanced journal entries
Idempotency Safe retries for financial operations
RBAC Role hierarchy with granular permissions
Real-time Events SSE for instant balance updates
Service Isolation Each service owns its domain completely

India-First Design

Most fintech demos assume USD, US phone numbers, US regulations. Nivo is built for India:

  • Currency: INR stored as paise (smallest unit)
  • KYC: PAN and Aadhaar validation
  • Phone: +91 format validation
  • Timezone: IST (Asia/Kolkata)
  • UPI: Simulated UPI deposit flow

This isn’t just localization — it’s demonstrating understanding of a specific market’s requirements.


The Architecture Story

Why Microservices?

Not because they’re trendy. Because the domains are genuinely different:

graph LR
    subgraph "User Domain"
        I[Identity<br/>Auth, KYC]
        R[RBAC<br/>Permissions]
    end

    subgraph "Financial Domain"
        W[Wallet<br/>Balances]
        T[Transaction<br/>Transfers]
        L[Ledger<br/>Bookkeeping]
    end

    subgraph "Support Domain"
        K[Risk<br/>Fraud]
        N[Notification<br/>Alerts]
        S[Simulation<br/>Demo Data]
    end

    I -.->|validates| T
    R -.->|authorizes| T
    T -->|updates| W
    T -->|records| L
    T -.->|checks| K
    T -.->|notifies| N
  • Identity cares about users and authentication
  • Ledger cares about accounting accuracy
  • Risk cares about fraud patterns
  • Transaction orchestrates them all

These are different concerns with different change rates. Microservices let them evolve independently.

Why Double-Entry Bookkeeping?

Simple balance tracking seems easier:

wallet.balance = wallet.balance + amount

But what happens when:

  • A bug credits an account twice?
  • An admin needs to know where money came from?
  • A regulator asks for a complete audit trail?

Double-entry makes these problems impossible:

sequenceDiagram
    participant T as Transaction
    participant L as Ledger
    participant DB as Database

    T->>L: Transfer ₹1,000

    L->>DB: Begin Transaction
    L->>DB: Debit: Source Wallet ₹1,000
    L->>DB: Credit: Dest Wallet ₹1,000
    L->>DB: Verify: Debits = Credits
    L->>DB: Commit

    Note over L,DB: If debits ≠ credits,<br/>entire transaction fails

Every rupee has a source. Every rupee has a destination. The books always balance.

Why JWT + RBAC?

Sessions are simpler, but they don’t scale:

graph TB
    subgraph "Session-Based (Doesn't Scale)"
        C1[Client] --> G1[Gateway]
        G1 --> S1[Session Store]
        S1 --> A1[Service A]
        S1 --> B1[Service B]
    end

    subgraph "JWT-Based (Scales Horizontally)"
        C2[Client] --> G2[Gateway]
        G2 --> A2[Service A]
        G2 --> B2[Service B]

        Note1[Each service validates<br/>JWT independently]
    end

With JWT:

  • No shared session store
  • Services validate tokens independently
  • Scales to any number of instances
  • Permissions embedded in token

What Nivo Teaches

For Engineers

  • How to structure a Go microservices project
  • How double-entry ledger systems work
  • How to implement proper RBAC
  • How to handle financial transactions safely
  • How to build real-time features with SSE

For Architects

  • When microservices make sense (and when they don’t)
  • How to draw service boundaries
  • How to handle cross-service transactions
  • Trade-offs between consistency and availability

For Hiring Managers

This project demonstrates:

Skill Evidence
System Design 9 services with clear boundaries
Domain Knowledge Double-entry ledger, KYC, risk management
Code Quality Consistent patterns across all services
Production Thinking Idempotency, graceful shutdown, structured logging
Documentation ADRs, flow diagrams, API docs

What Nivo Doesn’t Do

Being honest about scope is as important as showing capability:

Feature Status Why
Real payments Simulated Regulatory compliance, banking licenses
Multi-currency INR only Scope control, India-first design
Mobile apps Web only Focus on backend architecture
High availability Single instance Demo scope, not production deployment
Event sourcing Not implemented Double-entry provides sufficient auditability

These aren’t limitations — they’re deliberate scope decisions. A project that tries to do everything does nothing well.


The Technical Journey

Phase 1: Foundation

Core services with basic functionality:

  • Identity (auth, users)
  • Ledger (accounts, entries)
  • Wallet (balances)
  • Gateway (routing)

Phase 2: Financial Features

Complete transaction flows:

  • Deposits, withdrawals, transfers
  • Risk evaluation
  • Beneficiary management
  • RBAC permissions

Phase 3: Polish

Production-readiness:

  • Real-time SSE events
  • Simulation engine for demo data
  • Admin dashboard
  • Observability with Prometheus/Grafana

Phase 4: Documentation

You’re reading it. Because code without context is just text.


Try It Yourself

Live Demo

Nivo has three frontend applications, each serving a distinct purpose:

App URL Purpose
User App nivomoney.com Customer-facing banking
Verify Portal verify.nivomoney.com Transaction verification for paired users
Admin Dashboard admin.nivomoney.com Operations and KYC management

User Appnivomoney.com

Email: raj.kumar@gmail.com
Password: raj123

The main banking experience: dashboard, transfers, transaction history, profile management.

Verify Portalverify.nivomoney.com

Email: priya.electronics@business.com
Password: priya123

For trusted verifiers (family members, guardians) to view OTP codes and approve transactions initiated by their paired user. Useful for accessibility or shared account management.

Admin Dashboardadmin.nivomoney.com

Email: admin@nivo.local
Password: (generated at seed time - see .secrets/credentials.txt)

Internal operations: KYC review and approval, user management, system health monitoring.

Run Locally

git clone https://github.com/1mb-dev/nivomoney.git
cd nivomoney
make dev

See the Quick Start for detailed setup.


Conclusion

Nivo isn’t trying to be a real bank. It’s trying to show how a real bank works.

The value isn’t in the features — it’s in the architecture, the patterns, and the decisions. Every design choice has a reason. Every trade-off is documented.

If you’re building fintech systems, or want to understand how they work, Nivo is a practical reference. Not perfect, but real.


Built with Go, React, and strong opinions about software architecture.