N
All work

Full-Stack Engineer · 2021 · 12 months

Building a multi-tenant LMS for 5,000+ students

LaravelVue.jsMySQLStripeZoom API

Tutors needed independently branded academies without engineering involvement. I architected an isolated multi-tenant system with subscription billing, seven payment gateways, and live Zoom classes serving thousands of students.

5,000+Students
7Payment gateways
Multi-tenantArchitecture

Context

Each tutor wanted their own branded academy — custom domain, courses, subscriptions, and live classes — without waiting on engineering to spin up infrastructure per customer. The platform had to feel bespoke to every tenant while running from one codebase.

Constraints

  • Strict tenant isolation — no tenant could ever see another's students, revenue, or content.
  • Seven payment gateways across regions (PayPal, Stripe, Razorpay, Cashfree, Instamojo, PayUMoney, Flutterwave), each with its own webhook and reconciliation model.
  • Live class scheduling integrated with Zoom, tied to subscription entitlements.

Approach

  • Tenant-scoped data model with a shared schema and enforced tenant keys at the query layer, so isolation was structural rather than convention.
  • A gateway abstraction normalized seven providers behind one billing interface, with webhooks reconciled into a single subscription state machine.
  • Zoom API integration provisioned meetings on demand and gated access by subscription tier.

Architecture

A single Laravel application resolves the tenant from the request, scopes every query to it, and drives a Vue SPA. Billing and Zoom live behind provider-agnostic service interfaces.

Results

  • 5,000+ students served across independently branded academies.
  • Seven gateways unified behind one subscription lifecycle.
  • Self-serve onboarding — tutors launched academies without engineering involvement.

What I'd do differently

I'd extract the gateway abstraction into a standalone package from day one; it was reusable well beyond this product and we recognized that only late.