All projects

Mango Capital: CI/CD and Production Stabilization

Owned the GitLab CI/CD and Docker deploys for a trading and funding platform, fixed the failures that only happen in production, and built trading, funding, and billing features.

Role
Full-stack engineer on a team project; owned CI/CD
System
Mango Capital trading and funding platform (Dubtel)
A CI pipeline feeding containers connected to a database with a connection gauge

Results at a glance

  • GitLab CI pipelines deploying Docker containers to QA and production, with migrations run as part of the deploy.
  • Fixed Postgres connection exhaustion by sizing gunicorn workers and SQLAlchemy pools against the database's limit.
  • Production configuration injected from GitLab file variables at deploy time.
  • Added a /health endpoint reporting the build SHA and time, which ended 'is the new code live?' guesswork.
  • Built the trades and profitability report pages, the buy-model screens, funding-request listings with funder email notifications, and billing with server-side PDF invoices.

Overview

Mango Capital is a trading and funding platform built at Dubtel. It was a team project. My part covered two areas: owning the delivery pipeline, and building features across the API, the funding portal, and the frontend.

Owning CI/CD

I set up and maintained the GitLab CI pipelines that build Docker images and deploy them to QA and production. Getting them reliable meant working through the failures that only show up on real servers:

  • Disk and tmpfs. Deploys failed on full disks and stale tmpfs state. The pipeline now prunes Docker resources before building, cleans up containers and frees ports before starting, and prints diagnostics when something goes wrong.
  • Migrations. flask db upgrade runs on every deploy. It kept hanging because live containers (the API and a Swagger UI) still held database connections. Stopping one service wasn't enough; the reliable fix was docker compose down on the whole stack before migrating.
  • Config. Production configuration is injected from a GitLab file variable at deploy time.
  • Provenance. A /health endpoint returns the build SHA and timestamp, so anyone can check what's deployed.

Fixing production

  • Connection exhaustion. Each gunicorn worker opens its own SQLAlchemy pool. Four workers with default pools, plus other containers, exceeded the managed Postgres limit. I cut the workers to two, capped each pool at 3 connections plus 2 overflow (10 total), and wrote that arithmetic into the config. The managed database sits behind PgBouncer, which also needed sslmode=require on every connection URL.
  • Surprise JOINs. A relationship declared lazy="joined" added a JOIN to every user lookup. Switching it to select made the hot path cheaper.
  • CORS with credentials. Browsers reject a wildcard origin on credentialed requests. The API now reflects the request's Origin for allowed origins. I briefly replaced Flask-CORS with a hand-written handler, then went back to Flask-CORS once it was configured correctly, because less custom code is better.
  • Logging that crashed logins. A failure writing a log row to the database turned logins into 500s. Logging failures are now caught and never fail the request.

Features

  • Trading: trades and profitability report pages with pagination, and the buy-model screens.
  • Funding: a listing of all submitted funding requests for admins, admin notes, and email notifications to funders, requesters, and the company.
  • Billing: billing models and endpoints with Swagger docs, and server-side PDF invoices with WeasyPrint. WeasyPrint's limited flexbox support needed a table-based layout.
  • White-label support: tenant logo upload to object storage, used in the login response and on PDF invoices.

What I took from it

  • Write the connection arithmetic down next to the pool config.
  • Stop everything that holds a database connection before migrating, not just the service you know about.
  • Every deploy should be able to prove which commit it's running.
Henry Iddirisu

Henry Iddirisu

AI product engineer · Accra, Ghana · Remote

More projects

PythonFastAPISQLAlchemy (async)

DUBTEL AI Platform Backend

Role: Backend engineer (built solo); led the Next.js portal

The multi-tenant FastAPI backend for an AI voice-agent platform, built solo: tenants, role hierarchy, SAML SSO, pricing, recurring…

Next.jsReactTypeScript

DUBTEL AI Portal

Role: Lead frontend engineer

The white-label Next.js portal where businesses manage AI voice agents, phone numbers, billing, and users, with role-aware navigat…