Accessibility settings

Changes apply right away and are remembered in this browser. Until you choose otherwise, motion follows your device's setting.

Motion
Text size
Reading

LMS Platform Modernization

After a few years of keeping the Legacy LMS healthy on an end-of-life stack, I wrote up a plan to modernize it from the ground up: the stack, the hosting model, the delivery pipeline, and the migration path for every client. The plan was the point. But I couldn’t stop thinking about it, so I started building it on my own time to find out whether it holds up.

The result is a full rebuild of a multi-tenant learning platform: Laravel 11 on PHP 8.3 instead of PHP 5.6 and Phalcon, an Angular 19+ Nx monorepo instead of AngularJS 1.7, and an isolated server for every client instead of shared ones.

Written up as a modernization plan for a legacy LMS, then built independently as a personal project to prove the plan.

Out with the old

Every layer of the stack gets a fresh start:

  • Backend: PHP 5.6 and Phalcon 2 → Laravel 11 on PHP 8.3
  • Frontend: AngularJS 1.7 → Angular 19+ in an Nx monorepo
  • Hosting: shared servers → a Terraform-provisioned, isolated EC2 instance per client
  • Delivery: hand-configured Jenkins jobs → a GitLab CI/CD pipeline (test, build, deploy)

One client, one server, zero hands

The biggest architectural change is isolation. In the Legacy LMS, every client shares the same servers and the separation happens in code. In the new platform, Terraform provisions a separate EC2 instance for each client, and cloud-init bootstraps it from scratch with nobody logging in to set it up. Data isolation rolls out in phases, so the move can happen gradually instead of in one terrifying weekend.

Getting clients there is its own project, so I built custom tooling that pulls data from the Legacy LMS, transforms it for the new schema and loads it into the new platform.

Per-client infrastructure Terraform provisions a separate, isolated EC2 instance for each client. Each instance bootstraps itself with cloud-init, with no manual setup. Migration tooling extracts each client's data from the Legacy LMS, transforms it for the new schema and loads it into that client's instance on the new platform. provisions Terraform one instance per client Client A · EC2 cloud-init, zero-touch setup Client B · EC2 cloud-init, zero-touch setup Client C · EC2 cloud-init, zero-touch setup Migration tooling extract, transform, load Legacy LMS data source platform
Terraform provisions an isolated instance per client, cloud-init sets each one up automatically, and migration tooling brings each client’s Legacy LMS data across.

Designed, not inherited

Users with a real lifecycle

Accounts move through clear states (pending, active, deactivated), gated by email activation. That’s a direct lesson from the Legacy LMS, where I once found a deactivated user could reactivate themselves through a password reset. In the new platform, the account lifecycle is designed in from the start instead of patched on later.

  • Role-Based Access Control
  • Laravel

Categories and groups

Each user belongs to exactly one category, and can join any number of groups for course assignment.

  • Data Architecture
  • Laravel
  • Angular
  • TypeScript

A pipeline from day one

GitLab CI tests, builds and deploys every change, so the new platform starts life with the delivery habits the old one had to have bolted on later.

  • GitLab
  • CI/CD

Claude as a research partner

I use Claude to dig through how the legacy platform actually behaves and to scaffold new work, which keeps a one-person rebuild moving at a steady clip. The architecture and the plan are mine; the AI helps me get there faster.

  • AI-Assisted Development

Looking back

Maintaining the Legacy LMS taught me where it hurts. The plan, and the rebuild behind it, is my chance to design those pain points out instead of working around them.

Stack & skills

  • Laravel 11
  • PHP
  • Angular 19+
  • Nx
  • Terraform
  • cloud-init
  • AWS EC2
  • GitLab CI
  • Laravel
  • Angular
  • IaC
  • GitLab
  • AWS
  • Multi-Tenant Architecture
  • Data Migration
  • Role-Based Access Control
  • TypeScript