All work

Case study 05

LearnHub

A multi-tenant video platform that was going to live on one VPS behind a process manager. I re-planned it onto Kubernetes — and kept it inside the cost estimate I'd already given the client.

Role
Platform / deployment + full-stack
Timeline
May 2026 — ongoing · largest project by effort
Platform
K3s · ArgoCD · Docker · MinIO · Infisical · GitHub Actions

The re-platforming decision

The original plan was a single VPS with a process manager — the default for a project this size, and genuinely fine until it isn't. Two things made it the wrong choice here:

  • Video transcoding is bursty. Encoding jobs need to scale independently of the API serving students, and a single box forces them to compete.
  • It is a white-label product. Multiple organisations run on the same system, so "restart the server" is never a small decision.

I moved it to Kubernetes with ArgoCD GitOps, a self-hosted secret manager and self-hosted S3-compatible object storage. The constraint I set myself was that this must not blow the infrastructure budget I had already put in the architecture document — self-hosting the storage and secret layers is what made that possible.

Deployment architecture

  • Manifests split across application, infrastructure and ArgoCD directories, so the delivery layer is versioned separately from what it delivers.
  • Dockerfiles per service, with CI and build-deploy workflows building and publishing images.
  • Self-hosted object storage for media instead of a managed bucket, which is the single largest cost line in a video product.
  • Two security audits run against the deployment before it carried real users.

Local development deliberately uses non-default database ports so the project runs alongside other projects on the same machine without a port collision — a small thing that stops "works on my machine" from becoming a daily tax.

What the platform had to support

The deployment work only makes sense against what runs on it, so briefly: this is a white-label Udemy-style learning platform I built from requirements documents through to production — a business requirements doc, a spec covering 70+ functional requirements across 16 collection schemas, a functional document spanning 19 modules, and a nine-section architecture document with the cost estimate.

  • Multi-tenancy with path-based organisation routing, org-scoped registration, per-organisation theming from two brand colours, and generated public landing pages. Tenant lookup is cached in Redis so it isn't a database hit on every request.
  • Four-role access control — super admin, organisation admin, instructor, student — with short-lived access tokens, rotating refresh tokens and per-role device limits.
  • A video pipeline: chunked upload to object storage, a job queue driving FFmpeg to transcode into HLS at four renditions off the request path, and signed-URL streaming with a moving per-organisation watermark.
  • Progress tracking that writes through a Redis cache — heartbeat every ten seconds, batched to the database every sixty — so accurate resume behaviour doesn't create a write amplification problem.

Indexes are state, not code. After a schema change, user creation started failing on stale partial-filter unique indexes left over from the previous shape. Dropping and recreating them fixed it — a reminder that a database carries history your repository doesn't, and that migrations need to account for what already exists rather than what the model says should.

Ongoing

I still review pull requests on this codebase — including catching placeholder marketing copy that had been committed as real schema defaults, and verifying the fix actually landed in the follow-up commit rather than taking the description's word for it.

Outcome

  • A reproducible, GitOps-delivered deployment replacing a single-server plan.
  • Transcoding that scales independently of the API serving students.
  • Self-hosted storage and secrets keeping running cost at the estimated figure.
  • Two security audits completed before real users arrived.

Back to the start

NGO Platform & Community App