Back to Projects
Fintech Platform

Gcbuying

A gift-card-and-crypto fintech platform serving 300K+ users. Hired on Fiverr to work on a Laravel monolith, I became the lead developer and rebuilt it single-handed into 17 NestJS microservices — with crypto rails, a mobile app, and a double-entry ledger on live money.

10 min read300K+ Users
300K+ active usersLaravel monolith → 17 NestJS microservices400K+ transactions on a double-entry ledgerMulti-provider on-chain crypto railsWeb, admin, landing & mobile app

Tech Stack

NestJSMicroservicesKubernetesMongoDBRabbitMQGraphQLReactNext.jsReact NativeTerraformRedisLaravel

Overview

Gcbuying is a Nigerian fintech platform where 300K+ users trade gift cards and cryptocurrency for Naira, run on-chain deposits, pay bills, and complete KYC. I was hired on Fiverr in 2020 to work on it — and over five years I grew into the lead developer the platform ran on, re-architected it from a Laravel monolith into a NestJS microservices system, and carried it to production scale.

I'm a developer, not the founder: the product, brand, and business direction were the founder's; I owned the engineering. What follows is that engineering story — how the platform was built, rebuilt, and hardened over five years.

At a glance

Span2020 → 2026 (~5 years)
My roleFiverr contractor (2020) → lead / primary developer
The pivotRe-architected a Laravel monolith → NestJS microservices, single-handed (2022)
End state17 microservices · web app · admin dashboard · landing site · mobile app
DomainCrypto trading, wallets, on-chain deposits, gift cards, bill payments, KYC, referrals
Headline winMigrated 400K+ transactions onto a double-entry ledger on live money — books balanced to zero

Origin — the Laravel monolith (2020–2022)

When the founder hired me on Fiverr in 2020, Gcbuying was a single Laravel application with a narrow scope: sell gift cards, hold a Bitcoin wallet, and — critically — settle Bitcoin sells by hand. It worked and it made money, but it was a monolith with a manual operational core: one codebase, one database, one deploy.

As the founder's ambitions grew toward real-time trading, automated settlement, multiple chains, and compliance, the architecture that launched the business became the thing holding it back. A bug in one feature risked the whole app, manual settlement didn't scale, and there was no clean way to add genuinely independent capabilities like KYC or automated deposits. That tension set up the biggest decision of the project.

The pivot — rebuilding as microservices (2022)

In late 2022 I re-architected the platform from the ground up: the Laravel monolith retired in favor of a NestJS microservices system, designed and built single-handed. This is the centerpiece of the whole five years.

A two-week founding sprint set the shape of everything after it:

  • The first servicesauth, orders, products, trades, emails, then wallets. The manual Bitcoin process the monolith depended on was being replaced by a real wallet-and-trade engine.
  • Kubernetes from day one — Helm charts appear among the very first commits. The goal was independent, scalable deployment from the start, not a slightly bigger monolith.
  • A React frontend rebuilt alongside it.

Why rewrite at all — the riskiest thing an engineer can propose? Because the monolith's limits were architectural, not incremental. Automated settlement, multiple blockchains, and compliance each needed their own lifecycle, failure isolation, and deploy cadence. You can't bolt independence onto a monolith.

From prototype to product (2023)

2023 turned the rebuilt platform into something users could trust with an account, on three parallel threads:

  • Trust and identity. Forgot-password and email-verification flows, refresh-token rotation, and — notably early — 2FA in February 2023. Account security landed while the rebuild was still young.
  • Real-time and multi-surface. A chats service on Socket.IO, an images service for S3 uploads, a Strapi CMS, and a Next.js landing site. The platform became a full product surface — app, content, and marketing — not just an API.
  • The cloud migration most people never see. Infra commits trace a full AWS EKS → Google Cloud (GKE) migration, done while the platform kept shipping, with infrastructure split into its own repository so it could version independently from the code.

Crypto rails and compliance (2024)

This is the year the platform earned the word "fintech," and where the manual Bitcoin process of the Laravel days was finally automated and generalized.

  • KYC — identity verification as a first-class service, with document types expanding through the year.
  • Automated on-chain deposits. Rather than depend on a single vendor, I integrated multiple blockchain infrastructure providers behind a common abstraction — with webhook handling, address generation, and confirmation logic across several chains. A missed deposit is a customer's money lost, so correctness here was non-negotiable.
  • Gift-card buying — a dedicated service let the original "sell gift cards" business now run in both directions, through a third-party gift-card API.
  • Withdrawal controls — limits, stats, and approval flows: the guardrails for money leaving the system.
  • Role-based access — a full RBAC overhaul (super admin, sub-admin, operator, payment-manager roles, admin 2FA) turning the back office into a real, permissioned operations tool.

The decision that mattered: treating crypto providers as swappable. On-chain infrastructure has outages and regional gaps — the multi-provider design made a single point of failure into a config choice.

Scale, growth loops, and observability (2025)

The busiest year by far — over 300 backend commits — and a clear shift from "does it work?" to "does it grow, and can we see what it's doing?"

  • Growth engineering. In a single week, four services landed together — referrals, leaderboards, rate-alerts, and transactions — a coordinated engagement layer with referral rewards, competitive leaderboards, price alerts, and GraphQL-backed analytics. Loyalty streaks and leadership bonuses followed.
  • The mobile app comes of age. The React Native / Expo app ramped hard through the year — analytics, streaks, push notifications, BNB support, mobile attribution, and parity with the web app's core flows.
  • Bill payments. The ebills service extended the platform from crypto and gift cards into utility payments — new revenue on the same wallet backbone.
  • Seeing the system. A real observability stack arrived: Sentry wired across every module, then Prometheus + Grafana with service monitors and dashboards for Redis and RabbitMQ, plus Redis caching on the trading rate engine. The platform went from a black box to something you could watch.

Financial rigor — the double-entry ledger (2026)

With scale came scrutiny, and 2026 was about making the platform's accounting provably correct. This is the technical highlight of the whole project.

The wallet system tracked balances with direct increments (wallet.balance += amount) — functional, but with no independent guarantee that every movement of money had an equal, opposite counterpart. I introduced a double-entry accounting ledger (LedgerAccount + JournalEntry) where every user credit pairs with a system-account debit, so the grand total across all accounts must always be zero.

The cutover was incremental and reversible:

  1. Dual-write behind a LEDGER_ENABLED flag — every wallet mutation wrote both the legacy increment and a balanced journal entry, atomically, with old paths untouched for instant rollback.
  2. Route every money-movement flow through it — all ~19 ways money could move (gift-card sales, crypto/VIP deposits, withdrawals and cancellations, admin adjustments, referral rewards, streak and leadership bonuses, bill-payment debits and refunds). An audit caught two flows still bypassing it; closing them was the difference between "mostly ledgered" and "provably complete."
  3. Backfill history — a migration replayed 400K+ historical transactions as legacy-marked entries and reconciled them against existing balances.
  4. Flip the source of truth once the books matched.

The outcome: a ₦0 grand-total invariant, a migration of 400K+ entries running in ~8 seconds from inside the cluster, and the only discrepancies a single pre-flip withdrawal and 21 kobo of floating-point drift — each closed with a targeted, idempotent adjustment. I built operators a Ledger Health dashboard to confirm the books are sound at a glance.

Resilience. A poison-message redelivery loop (one incident cycled 100M+ times, saturating error reporting) drove a fix: producer-side input guards plus a shared nackOnError helper that rejects deterministically-doomed messages without requeuing, while still retrying transient ones. The platform then adopted dead-letter exchanges (DLX) to quarantine poison messages instead of looping them.

Consolidation. Late in the journey I merged the standalone bank-deposits service back into wallets (18 → 17). It was a thin slice of behavior that fundamentally mutated wallet balances and shared their transactional boundaries — splitting it bought a network hop and a desync risk with no domain independence in return. Knowing when not to split a service is as much a skill as knowing when to.

The architecture that emerged

What five years and one rewrite produced:

plaintext
├── API Gateway (Nginx / Kubernetes Ingress)
├── 17 NestJS microservices  ──  RabbitMQ · MongoDB replica sets · Redis
│     auth · orders · products · trades · wallets · deposits · kyc
│     giftcards · referrals · leaderboards · rate-alerts · transactions
│     ebills · chats · images · emails · …
├── @app/common  (shared library, 80+ exports)
│     AbstractRepository · auth/RBAC · RabbitMQ wrapper
│     S3 · email · Sentry · Prometheus · the ledger
└── Surfaces:  Web (React) · Admin (React + MUI) · Landing (Next.js) · Mobile (React Native)
  • A monorepo of git submodules — backend, web, admin, landing, mobile, and infra deploy independently but share conventions.
  • 17 NestJS microservices over RabbitMQ, MongoDB replica sets, and Redis, behind an Nginx/API gateway. REST for most endpoints, code-first GraphQL (Apollo) for transaction history, Socket.IO for chat.
  • A shared @app/common library (80+ exports) holding what must be identical everywhere — the AbstractRepository base class, auth/RBAC, the RabbitMQ wrapper, S3/email/Sentry/Prometheus infrastructure, and the ledger.
  • GKE on GCP, deployed via Helm, provisioned with Terraform, observed with Sentry + Prometheus + Grafana.

None of it was designed up front. It accreted from a monolith — each layer added because the previous one made it necessary.

Lessons from five years on one platform

  • Earn the right to rewrite, then commit fully. Rewriting the Laravel monolith was the biggest risk I took — justified because the limits were architectural, not incremental. When the ceiling is the architecture itself, incremental fixes only delay the rebuild.
  • But over-splitting has a cost too. The bank-depositswallets merge corrected my own earlier instinct. Service boundaries should follow transactional boundaries, not neatness.
  • Observability is a prerequisite for change. The 2026 ledger migration was only safe because of the 2025 observability work. Next time I'd build the correctness dashboard even earlier — it would have caught the bypassing flows by watching the invariant instead of by auditing code.
  • Money is integers. The 21-kobo drift was recoverable, but it was a symptom: monetary amounts should be integer minor units end to end from day one, never floats.
  • Make rollback as deliberate as rollout. The flag made enabling the ledger safe; rolling back after it went live required a data migration. Design the reverse path with the same care as the forward one.

Tech stack

Built with

  • Backend: NestJS, TypeScript, MongoDB/Mongoose, GraphQL (Apollo, code-first), RabbitMQ, Redis, Bull queues, Passport/JWT, Socket.IO
  • Web: React, TypeScript, Vite, Redux Toolkit + RTK Query, Apollo Client, Tailwind CSS
  • Admin: React, MUI + Data Grid, Chart.js, Redux Toolkit + RTK Query
  • Landing: Next.js (App Router), Tailwind, Strapi CMS
  • Mobile: React Native, Expo, NativeWind, Redux Toolkit, Apollo Client, Firebase
  • Origin (2020–2022): PHP / Laravel monolith — retired in the 2022 rewrite

Ran on

  • Cloud: Google Kubernetes Engine (GKE) on GCP — migrated from AWS EKS in early 2023
  • Deploy / IaC: Helm, Docker, Terraform, Nginx gateway
  • Observability: Sentry, Prometheus, Grafana

Want Your Own Exchange?

I build production-ready cryptocurrency exchanges with advanced trading engines, secure wallet systems, and real-time order matching.

View Gig