Retour aux projets
Fintech

Cross-Border Payments Platform

A cross-border B2B and B2C payments platform I designed and built end to end, moving money across underserved African corridors in under 24 hours.

NestJS nextjs PostgreSQL
Cross-Border Payments Platform

Overview

A cross-border payments platform for B2B and B2C transfers across underserved corridors. Companies that pay foreign suppliers through informal brokers or SWIFT (30 to 45 days) can send money in under 24 hours, at a rate guaranteed when the transfer is quoted, with full traceability and a signed receipt. Starting from nothing but a vague idea, I owned the whole thing end to end, product and engineering: the backend, the client portals and the operations back-office.

The problem

Moving money out of Central Africa is slow, opaque and expensive. Correspondent banking over SWIFT can take 30 to 45 days, and the informal alternative through brokers offers no guaranteed rate and no traceability. The platform closes that gap with fast, transparent and auditable transfers.

Corridors

  • XAF to EUR and XAF to USD, fully automated
  • XAF to CNY, handled through a local broker with an operator in the loop

The automated corridors settle over stablecoin rails instead of slow correspondent banking, which is what makes sub-24-hour delivery possible while keeping a guaranteed rate.

What it does

For senders (business and individual)

  • Create and track transfers with the rate locked at quote time
  • Full traceability across each transfer's lifecycle
  • Downloadable, QR-signed receipts and transfer documents
  • One unified portal for both business and individual users

Operations and compliance back-office

  • A dedicated back-office for Ops and Compliance teams
  • Transfer processing, review, reconciliation and manual corridor settlement
  • Just-in-time KYC review, document-requirement rules, and regulatory controls
  • System settings with encrypted credentials and role-based administration

Engineering

This is a payments system, so correctness under failure and retries mattered more than features. The parts I am most proud of:

Backend-for-frontend (BFF). The browser never talks to the payments API directly. Both the client portal and the back-office are Next.js apps that proxy every call through server-only code, custody the session in httpOnly cookies, and forward it to an internal-only API. Two separate session namespaces isolate client and admin. Mutations go through server actions with shared Zod validation at the edge, and documents stream through server route handlers so the API is never exposed to the browser.

Money handled like money. Every amount is stored as an integer in minor units, never a float. Pricing and FX are computed in fixed-point arithmetic with an explicit rounding policy so the platform never under-collects. Balances live in an append-only ledger where each posting records the resulting balance and is made idempotent by database constraints, so a provider retry can never double-credit an account. Reconciliation jobs align internal balances against the provider.

Correct under retries. Every money endpoint is idempotent: an idempotency key is stored with a hash of the request, so a retry returns the original result while a different payload under the same key is rejected. The client rotates its key whenever the money intent changes, so a retry after 2FA can never replay a stale transfer. A transfer moves through a centralized 13-state machine, enforced both in code and by database constraints, and every transition is written to an immutable event log.

Async and resilient. The transfer lifecycle runs on background workers (BullMQ on Redis) with exponential-backoff retries, plus scheduled jobs for expiry, status polling and reconciliation. Inbound provider webhooks are signature-verified, deduplicated by event id and processed exactly once, then side effects are dispatched only after the database commits.

Guaranteed rate. When a transfer is quoted, the rate and all fees are snapshotted onto the transfer as immutable values with an expiry, so a later price change can never retroactively alter an existing transfer.

Provider-agnostic orchestration. Payment providers sit behind a single adapter interface, so a stablecoin orchestration rail (automated corridors) and a local XAF settlement rail (manual broker corridor) plug in the same way. A stateless routing engine selects the corridor and provider by segment (B2B or B2C), disbursement method, amount bounds and priority.

Compliance and audit. KYC and identity verification are enforced just-in-time at commit and delegated to a specialized identity provider, with document-requirement rules that hold a transfer until Compliance approves. Regulatory purpose codes and per-owner spending limits are enforced, and every sensitive action is written to an immutable, append-only audit log.

Security. Opaque, server-side, revocable sessions sealed in httpOnly cookies rather than tokens in the browser, with step-up two-factor authentication (TOTP). Provider and integration secrets are encrypted at rest with AES-256-GCM. Inbound webhooks are verified by RSA signature with timestamp replay protection. Auth and money endpoints are rate-limited per owner and IP.

Tech stack

  • Monorepo: Turborepo + pnpm
  • Backend: NestJS + TypeScript, BullMQ workers on Redis 8
  • Frontends: two Next.js 16 (App Router) + React 19 apps (client portal and Ops/Compliance back-office) on a BFF architecture
  • Database: PostgreSQL 17 + Drizzle ORM, integer-money schema with CHECK invariants
  • Validation: Zod shared end to end, plus a shared design-system package
  • Testing: Vitest integration suite running against a real PostgreSQL database

My role

This was a 0-to-1 build. The client arrived with only a vague idea, and I owned everything from there, as both product architect and engineering lead.

On the product side, I ran the discovery and defined the product itself: the PRD, the business rules, the regulatory and compliance analysis, the glossary, and the design system and screen specifications.

On the engineering side, I set the technical architecture and built the platform end to end as lead developer: the BFF layer and both Next.js frontends, the NestJS backend and worker pipeline, the PostgreSQL and Drizzle schema, the integer-money and ledger core, the payments orchestration across automated and manual corridors, and the operations and compliance back-office. I then delivered it to production.