Back to work
2025·Fintech · TreasuryPRODUCTION

VAULTPAY

Programmable treasury for modern fintech.

A B2B treasury platform letting startups automate cash flow, reconcile transactions across banks, and forecast runway with ML-driven projections. One canonical view of money in motion.

Duration
14 weeks
Team
3 engineers + 1 designer
My role
Lead full-stack engineer
Outcome
Monthly active users
87.2k
+18% MoM
Transactions processed
2.4M
+34% QoQ
P95 latency
124ms
Uptime
99.98%
The story

From brief to production system.

Challenge

Finance teams juggle 4-7 disconnected dashboards. Reconciliation takes 3-5 days at month-end. Cash position is always 24+ hours stale. We needed sub-minute freshness across multi-bank, multi-currency operations — without forcing customers to migrate banks.

Solution

Event-sourced ledger with append-only journal, Kafka-style transaction streams, ML forecasting on Pandas + Prophet, and a real-time dashboard pushing diffs over WebSocket. Plaid + Stripe + custom bank adapters unified into one canonical model. Forecasts retrain nightly on a 90-day window.

Outcome

Cut reconciliation from 5 days to 8 hours. Reduced manual entry errors by 94%. CFOs report decisions made on data <60s old. 87k MAU across 4 countries within first 8 months. Currently processing $48M / month.

Process · 14 weeks

How it shipped, week by week.

Week 1-2
01 / 5

Discovery + ledger design

Mapped customer workflows across 12 finance teams. Settled on event sourcing as the foundation — single immutable source of truth.

Week 3-6
02 / 5

Adapter layer + canonical model

Built the bank adapter abstraction. Plaid and Stripe first, then 6 custom adapters for regional banks. Every adapter mapped to one canonical Transaction type.

Week 7-10
03 / 5

Reconciliation engine + dashboard

Built the streaming reconciliation pipeline. Real-time diff push to clients via WebSocket. Dashboard shipped feature-complete by week 10.

Week 11-13
04 / 5

ML forecasting + ops hardening

Trained Prophet models on historical cash flow. Added retry semantics, alerting, runbook. Soak-tested under simulated load.

Week 14
05 / 5

Launch + handoff

Migrated 12 pilot customers. Documented every system. Trained the customer's internal ops team. Production handoff was a 90-minute call.

Inside the system

What it does. How it's built.

Features

  • Multi-bank aggregation (Plaid + 6 custom adapters)
  • ML-driven 90-day cash forecasting
  • Real-time reconciliation engine with sub-minute freshness
  • Custom rules engine for transaction categorization
  • Audit log with cryptographic chaining
  • Role-based access control with SOC2-grade audit trails
  • Multi-currency support across 12 currencies
  • Programmable transfer schedules with retry semantics

Architecture

  • 01Next.js 15 App Router for dashboard SSR
  • 02Node.js services on AWS Lambda (event-driven)
  • 03PostgreSQL primary + Redis hot cache + S3 cold storage
  • 04Plaid + Stripe + 6 custom bank adapters unified behind a single port
  • 05WebSocket layer (Socket.io) for live updates to dashboard clients
  • 06Python ML pipeline (Pandas + Prophet) on scheduled ECS Fargate
  • 07ClickHouse for analytical queries on the transaction journal
  • 08Multi-region deployment (us-east-1, eu-west-1)
Stack
Next.js 15Node.jsPostgreSQLRedisAWS LambdaStripePlaidSocket.ioProphet (Python)ClickHouse
From the codebase

Annotated excerpts.

01 · Streaming reconciliation: batched matching with drift detection.
services/reconciliation.tstypescript
// Streaming reconciliation engine
export async function reconcile(
  txns: Transaction[],
  ledger: LedgerStream,
): Promise<ReconciliationResult> {
  const batched = batchByAccount(txns, { window: 60_000 });

  const results = await Promise.all(
    batched.map(async (batch) => {
      const expected = await ledger.expectedFor(batch.accountId);
      const matched = matchEntries(batch.entries, expected);
      const drift = computeDrift(matched);

      if (drift.delta > THRESHOLD_BPS) {
        await alertOps({ severity: "warn", batch, drift });
      }

      return { account: batch.accountId, matched, drift };
    }),
  );

  return aggregate(results);
}
02 · 90-day cash forecast: Prophet with custom regressors.
ml/forecast.pypython
def build_model(account_id: str, history: pd.DataFrame) -> Prophet:
    """Train a Prophet model with company-specific regressors."""
    m = Prophet(
        changepoint_prior_scale=0.05,
        seasonality_mode="multiplicative",
        interval_width=0.85,
    )

    # Custom regressors — payroll cadence, AR cycles
    m.add_regressor("is_payroll_day")
    m.add_regressor("ar_cycle_phase")
    m.add_seasonality(name="monthly", period=30.5, fourier_order=8)

    # Pakistan + US bank holidays
    m.add_country_holidays(country_name="US")

    m.fit(history)
    return m
What the client said
Ali rebuilt our reconciliation pipeline in three weeks. Cut what used to take five days down to under eight hours. He thinks like an owner — flagged three architectural risks we hadn't noticed and fixed two of them before we even prioritized.
SC
Sarah Chen
CTO · Northwind Capital
Other projects

Continue browsing

Have a project like this in mind? Let's talk.

Send me a brief and I'll respond within 24 hours.

← Home© 2025 Ali RazzaqContact →