Modernizing Mature Ecosystems: Clean Architecture & Performance in Read-Only Microservices

Published: (December 2, 2025 at 06:46 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

Scenario Overview

I recently tackled a common challenge in large corporate environments: creating new, high‑performance, scalable features that consume data from a consolidated database without compromising the stability of the central system.

The goal was to architect a Read‑Only Microservice to feed data‑visualization interfaces and export routines. Business requirements demanded rapid delivery, while the technical requirement I set for myself was engineering excellence and long‑term maintainability.

Key complexities

  • A relational (SQL) database with massive data volume and complex structures.
  • High Availability to serve multiple concurrent clients without blocking the Node.js event loop.
  • Strict security requirements and total isolation between Staging and Production environments.
  • AWS infrastructure that needed cost‑efficient optimization (compute/storage).

🇧🇷 Leia a versão em Português aqui

Clean Architecture Layers

To ensure longevity, I adopted Clean Architecture, isolating business rules from implementation details such as web frameworks or database drivers. The project was organized into four layers with defined responsibilities:

LayerResponsibility
DomainInterfaces and pure models of the application.
DataUse cases and business rules.
InfraExternal implementations (repositories, cryptography, integrations).
MainComposition layer that injects dependencies and initializes the service.

This separation allows, for instance, swapping the HTTP framework (e.g., Express → Fastify) or the ORM with zero impact on domain logic.

Data Access with Prisma

Mapping Existing Schema Safely

Manual SQL queries are fragile for future maintenance. I used Prisma ORM with its Introspection feature to read the existing schema and automatically generate TypeScript typings, avoiding the need for migrations (out of scope for this satellite service).

Handling Composite Keys

Older relationship tables use composite keys instead of unique identifiers. Prisma’s native schema mapping handles this cleanly:

model ExampleRelation {
  userId Int
  itemId Int

  // Defines unique identity by combining columns
  @@id([userId, itemId])
}

This brings type safety to data consumption, preventing runtime errors and accelerating development.

Infrastructure Optimization

Docker Multi‑stage Build

To keep images lightweight, I implemented a multi‑stage build using Alpine Linux:

  1. Builder Stage – installs dependencies, compiles TypeScript, generates artifacts.
  2. Runner Stage – copies only the transpiled dist folder and production dependencies.

Result: compact final images (~150 MB), faster deployments, and reduced storage costs in Amazon ECR.

PM2 in Cluster Mode

A standard Node.js process runs on a single core, underutilizing multi‑core cloud instances. Running PM2 in cluster mode spawns multiple workers based on CPU availability, optimizing throughput. If a worker restarts, PM2’s internal load balancer redirects traffic, maintaining service availability.

Architecture Diagram

Conceptual view of the proposed architecture

(Insert diagram image here)

CI/CD Pipeline and Environment Management

Consistency across environments is achieved with immutable artifacts:

  • A single Dockerfile is used for Dev, Staging, and Prod.
  • Sensitive environment variables are injected only at container runtime.
  • Environment segregation is handled via tags in the container registry.

Security Measures

  • Strict CORS middleware allowing only authorized domains.
  • Authentication validation on all routes.

These safeguards ensure isolation between environments and protect the read‑only service from unauthorized access.

Conclusion

This case study demonstrates that modern software engineering patterns can successfully modernize mature ecosystems. Combining Clean Architecture for organization, Prisma for type‑safe data access, and Docker/PM2 for operational efficiency yields a solid backend that is easy to maintain and ready to scale.

Back to Blog

Related posts

Read more »