— Case study

A 1,500-file PHP legacy, rebuilt into a modular monolith running four countries' training operations.

Liren Language & Communications runs corporate language training across Luxembourg, Belgium, France and the UAE. Feneco rebuilt the platform behind that operation — from an undocumented PHP system with no tests and no process, into a modular .NET monolith with real infrastructure, and an AI course builder with human approval designed into the data model, not bolted on top of it.

Client
Liren Language & Communications
Markets
Luxembourg, Belgium, France, UAE
Scale
15,000+ accounts, ~6,000 active
Status
Live in production

The legacy

~1,500 procedural PHP files, raw mysqli_connect calls, and a separate CodeIgniter "elearning" subsystem bolted on top — all on shared cPanel hosting. No versioned schema; it only existed in the live production database. No CI/CD, no infrastructure as code, no observability, no documentation, no tests. Every change was a direct edit against a system nobody could modify with confidence.

A modular monolith, not another quick fix

Feneco rebuilt Liren's core system as a modular monolith in .NET: CQRS with MediatR, EF Core over PostgreSQL, DDD-style aggregates with strongly-typed IDs, an outbox pattern for reliable domain events, and identity delegated entirely to Auth0. Ten focused projects — domain, infrastructure, contracts, services — replace the one undifferentiated PHP codebase.

Migrating data, not just code

With no versioned schema and a legacy password-hashing scheme incompatible with the new Auth0-backed identity system, this was never a schema-to-schema copy. The migration reads legacy data and writes it back through the same domain methods and invariants — global email uniqueness across HR, trainers and learners, among others — that the live application enforces, in a dependency-ordered load (companies → identity → HR/trainers/learners → enrollments → commercial/invoicing), with reconciliation and a rehearsed rollback before cutover.

Process where there was none

The entire AWS footprint — VPC, RDS, ECS Fargate, ALB, CloudFront/S3, Secrets Manager — is Terraform, deployed through GitHub Actions with OIDC, so there are no long-lived AWS credentials sitting in CI. Deploys are gated behind a required-reviewer environment. The database and load balancer have no public endpoint. The infrastructure region was chosen deliberately for latency to the actual client base across Luxembourg, Belgium and France — not defaulted to whichever region is cheapest or nearest to Feneco.

An AI course builder where "approved" is data, not a formality

Course modules move through an explicit generation lifecycle enforced by the domain model itself, not left to convention or UI state:

DraftGeneratingPending reviewApprovedPublished

Requesting generation and completing it are separate commands; a module can't be approved until it's actually been generated, and approval records exactly who approved it and when, directly on the entity. The AI writes drafts. A human decides what ships — and that decision is data, not a checkbox that disappears after the fact.

Status

Live in production, running Liren's training operations across Luxembourg, Belgium, France and the UAE.

If a legacy system is the thing standing between your team and how the business actually needs to run, let's talk.