All writing

Architecting AI Triage: Moving from Monolith to Microservices

Usama Razzaq

Full-stack systems thinker & mentor
  • System Design
  • NestJS
  • Microservices

Building a scalable system requires more than just picking the newest framework. It requires an understanding of the business constraints, team velocity, and first-principles thinking to determine what truly matters.

The Problem with "Just Rewrite It"

When engineers inherit a legacy PHP codebase, the immediate instinct is often to rewrite the entire thing in a modern stack like Next.js or NestJS. While this sounds appealing, it ignores the primary purpose of the codebase: serving users and generating revenue.

At Marham, we faced a similar situation. The monolith was slow, but it worked. Our AI Triage feature was becoming a bottleneck. Instead of a full rewrite, we opted for the Strangler Fig pattern.

The Microservice Extraction

By extracting just the AI Triage engine into an independent NestJS microservice, we gained the ability to scale horizontally where it mattered most, without destabilizing the core platform.


// Example of the NestJS controller handling the triage payload
@Post('analyze')
async analyzeTriage(@Body() payload: TriageDto) {
  // Process the payload asynchronously
  return this.triageService.processTriagePayload(payload);
}
      

Key Takeaways

  • Identify Bottlenecks: Don't guess. Use metrics to find out what is actually slow.
  • Incremental Migration: Use the Strangler pattern to slowly move pieces of the monolith to microservices.
  • Focus on Outcomes: Every architectural decision must map to a tangible business outcome.
"The best architecture is the one that gets out of the way and lets the product evolve."

By focusing on these principles, we improved patient flow significantly while maintaining high reliability.