All work

Spluur

Cloud deployment platform for developers in Africa, with multi-currency billing.

  1. GitHub
  2. API
  3. Queue
  4. Build
  5. Docker
  6. Traefik
  7. Live
How a push becomes a running deployment.

What it is

Spluur is a cloud hosting platform for developers in Africa. You connect a GitHub repository and it builds and deploys it. It also handles domains, managed Postgres and Redis, and it bills in five currencies, Naira included.

It runs on infrastructure I operate myself, on a Hetzner VPS. Tymbis, an event ticketing platform, runs its API and background workers on it.

What I built

  • A Fastify API and a Next.js dashboard
  • Deployment workers on BullMQ that build with Nixpacks and run each project in a Docker container
  • Traefik for routing and Let's Encrypt certificates, with custom domains
  • Postgres through Prisma, plus managed Postgres on Neon
  • Self-hosted Redis per project, each with its own network, password and memory cap
  • Domain registration through Openprovider
  • Billing in five currencies, with Paystack for payments

What broke

Custom domains that didn't route. The domain verification code changed Docker container labels, but Traefik wasn't configured to read them. Real routing came from YAML files the deploy worker writes. I fixed it by sending custom-domain changes through the same file writer the deploy worker uses.

Every visitor looked like the same IP. A wrong trustProxy setting meant req.ip silently stopped resolving the real address behind Traefik.

A migration history I had to untangle. I had used prisma db push instead of migrations for too long, so the migration history no longer matched the database. Cleaning that up taught me to treat migrations as the source of truth from day one.

Engineering decisions

Billing as four services. I'm redesigning billing so no single piece can do everything. A pricing service only produces quotes. A limits engine decides what a plan allows. A billing service turns quotes into charges. A wallet service is the only thing allowed to move money, and it's where Paystack is connected.

Redis moved in house. I migrated from Upstash to Redis containers I run myself, each isolated per project, with a weekly job that reaps idle ones.

What it runs on

TypeScript, Fastify, Next.js, Prisma and PostgreSQL, Redis, BullMQ, Docker, Traefik, Nixpacks, Paystack, Openprovider, Resend, Hetzner.

Next projectVysk