<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Leonardo Policarpo</title>
    <description>The latest articles on DEV Community by Leonardo Policarpo (@leonardopolicarpo).</description>
    <link>https://dev.to/leonardopolicarpo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3642176%2F31ae8246-0f05-480d-aae0-53af0db6735c.jpeg</url>
      <title>DEV Community: Leonardo Policarpo</title>
      <link>https://dev.to/leonardopolicarpo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/leonardopolicarpo"/>
    <language>en</language>
    <item>
      <title>Modernizing Mature Ecosystems: Clean Architecture &amp; Performance in Read-Only Microservices</title>
      <dc:creator>Leonardo Policarpo</dc:creator>
      <pubDate>Tue, 02 Dec 2025 23:46:12 +0000</pubDate>
      <link>https://dev.to/leonardopolicarpo/modernizing-mature-ecosystems-clean-architecture-performance-in-read-only-microservices-8hb</link>
      <guid>https://dev.to/leonardopolicarpo/modernizing-mature-ecosystems-clean-architecture-performance-in-read-only-microservices-8hb</guid>
      <description>&lt;h2&gt;
  
  
  Engineering strategies to decouple data retrieval, reduce infra costs, and scale Node.js apps.
&lt;/h2&gt;




&lt;p&gt;&lt;strong&gt;By Leonardo Policarpo&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Software Engineer | Backend Architecture &amp;amp; IoT Enthusiast&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href="https://dev.to/leonardopolicarpo/modernizando-sistemas-legados-clean-architecture-performance-e-docker-em-um-microsservico-3i95"&gt;🇧🇷 Leia a versão em Português aqui&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recently, I tackled a common challenge in large corporate scenarios: the need to create new, high-performance, scalable features that consume data from a &lt;strong&gt;consolidated database&lt;/strong&gt;, without compromising the stability of the central system.&lt;/p&gt;

&lt;p&gt;The goal was to architect a &lt;strong&gt;Read-Only Microservice&lt;/strong&gt; to feed data visualization interfaces and export routines. The business requirement was speed of delivery; the technical requirement I imposed on myself was &lt;strong&gt;engineering excellence and long-term maintainability&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I share the architectural decisions taken to ensure a robust and decoupled solution using &lt;strong&gt;Node.js, Clean Architecture, Prisma, and Docker&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. The Engineering Challenge
&lt;/h3&gt;

&lt;p&gt;The scenario involved complexities typical of robust systems that have grown organically over the years:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A relational database (SQL) with massive data volume and complex structures.&lt;/li&gt;
&lt;li&gt;The need for &lt;strong&gt;High Availability&lt;/strong&gt; to serve multiple concurrent clients without blocking the Node.js Event Loop.&lt;/li&gt;
&lt;li&gt;Strict security requirements and total isolation between Staging and Production environments.&lt;/li&gt;
&lt;li&gt;AWS Infrastructure that needed optimization for cost efficiency (Compute/Storage).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2. Clean Architecture: The Decoupling
&lt;/h3&gt;

&lt;p&gt;To ensure the project's longevity, I adopted &lt;strong&gt;Clean Architecture&lt;/strong&gt;. The main goal was to isolate business rules from implementation details like web frameworks or database drivers.&lt;/p&gt;

&lt;p&gt;The structure was organized into layers with defined responsibilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Domain&lt;/strong&gt;: Interfaces and pure models of the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data&lt;/strong&gt;: Use cases and business rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infra&lt;/strong&gt;: External implementations (Repositories, Cryptography, Integrations).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Main&lt;/strong&gt;: The composition layer that injects dependencies and initializes the service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation allows, for instance, replacing the HTTP framework (e.g., Express for Fastify) or the ORM in the future with &lt;strong&gt;zero impact&lt;/strong&gt; on the domain logic.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Integrating with Existing Bases (Prisma ORM)
&lt;/h3&gt;

&lt;p&gt;One of the technical challenges was mapping the pre-existing data structure safely and with type safety. Manual SQL queries tend to be fragile for future maintenance.&lt;/p&gt;

&lt;p&gt;The solution was to use &lt;strong&gt;Prisma ORM&lt;/strong&gt; with its &lt;em&gt;Introspection&lt;/em&gt; feature. Instead of managing migrations (which were out of scope for this satellite service), I configured Prisma to read the existing schema and automatically generate TypeScript typing.&lt;/p&gt;

&lt;p&gt;To handle older relationship tables that use composite keys instead of unique identifiers, I utilized native schema mapping:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model ExampleRelation {
  userId  Int
  itemId  Int

  // Defines unique identity by combining columns
  @@id([userId, itemId])
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This brought &lt;strong&gt;Type Safety&lt;/strong&gt; to data consumption, preventing runtime errors and accelerating development.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Performance &amp;amp; Efficiency: Docker and PM2
&lt;/h3&gt;

&lt;p&gt;Infrastructure optimization focused on reducing the memory footprint and maximizing CPU usage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker Multi-stage Build&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To avoid heavy images containing unnecessary development files, I implemented a multi-stage build using &lt;strong&gt;Alpine Linux&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Builder Stage&lt;/strong&gt;: Installs dependencies, compiles TypeScript, and generates artifacts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runner Stage&lt;/strong&gt;: Copies only the transpiled code (&lt;code&gt;dist&lt;/code&gt;) and production dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Result: Compact final images (around &lt;strong&gt;150MB&lt;/strong&gt;), resulting in faster deploys and reduced storage costs in the Container Registry (ECR).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PM2 in Cluster Mode&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Being single-threaded, a standard Node.js application uses only one processor core, which can underutilize resources in multi-core cloud instances.&lt;/p&gt;

&lt;p&gt;Implementing &lt;strong&gt;PM2 in Cluster Mode&lt;/strong&gt; allowed the application to scale vertically within the container. The manager spins up multiple processes (workers) based on CPU availability, optimizing throughput. Beyond performance, this strategy is crucial for resilience: if a worker needs to restart, the internal load balancer maintains service availability by redirecting traffic.&lt;/p&gt;

&lt;p&gt;Conceptual view of the proposed architecture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fis8x9m23si1kn6xduwta.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fis8x9m23si1kn6xduwta.png" alt=" " width="800" height="1422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Immutability and Security
&lt;/h3&gt;

&lt;p&gt;To ensure consistency across environments, I implemented a CI/CD pipeline based on immutable artifacts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single &lt;code&gt;Dockerfile&lt;/code&gt; is used for all stages (Dev, Staging, Prod).&lt;/li&gt;
&lt;li&gt;Sensitive environment variables are injected only at container runtime.&lt;/li&gt;
&lt;li&gt;Environment segregation via Tags in the Container Registry.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the application layer, security was reinforced with &lt;strong&gt;strict CORS middlewares&lt;/strong&gt; (allowing only authorized domains) and authentication validation on all routes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This case study demonstrates that it is possible to apply modern software engineering patterns to modernize mature ecosystems.&lt;/p&gt;

&lt;p&gt;The combination of &lt;strong&gt;Clean Architecture&lt;/strong&gt; for organization, &lt;strong&gt;Prisma&lt;/strong&gt; for data safety, and &lt;strong&gt;Docker/PM2&lt;/strong&gt; for operational efficiency resulted in a solid backend, easy to maintain, and ready to scale.&lt;/p&gt;

&lt;p&gt;Did you like the article? Connect with me on &lt;a href="https://www.linkedin.com/in/leonardodumont/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or check out my projects on &lt;a href="https://github.com/leonardopolicarpo/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>node</category>
      <category>aws</category>
      <category>docker</category>
      <category>cleanarchitecture</category>
    </item>
    <item>
      <title>Modernizando Ecossistemas Maduros: Clean Architecture e Performance em Microsserviços de Leitura</title>
      <dc:creator>Leonardo Policarpo</dc:creator>
      <pubDate>Tue, 02 Dec 2025 23:20:35 +0000</pubDate>
      <link>https://dev.to/leonardopolicarpo/modernizando-sistemas-legados-clean-architecture-performance-e-docker-em-um-microsservico-3i95</link>
      <guid>https://dev.to/leonardopolicarpo/modernizando-sistemas-legados-clean-architecture-performance-e-docker-em-um-microsservico-3i95</guid>
      <description>&lt;h2&gt;
  
  
  Como escalei uma arquitetura de leitura de dados reduzindo custos de infraestrutura e desacoplando um monólito legado.
&lt;/h2&gt;




&lt;p&gt;&lt;strong&gt;Por Leonardo Policarpo&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Engenheiro de Software | Arquitetura de Backend &amp;amp; Entusiasta de IoT&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href="https://dev.to/leonardopolicarpo/modernizing-mature-ecosystems-clean-architecture-performance-in-read-only-microservices-8hb"&gt;🇺🇸 Read the English version here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recentemente, trabalhei em um desafio comum em grandes cenários corporativos: a necessidade de criar novas funcionalidades performáticas e escaláveis que precisam consumir dados de uma base de dados consolidada, sem comprometer a estabilidade do sistema central.&lt;/p&gt;

&lt;p&gt;O objetivo era arquitetar um microsserviço &lt;em&gt;Read-Only&lt;/em&gt; (apenas leitura) para alimentar &lt;strong&gt;interfaces de visualização de dados&lt;/strong&gt; e rotinas de exportação. O requisito de negócio era agilidade na entrega; o requisito técnico que me impus foi &lt;strong&gt;excelência de engenharia e manutenibilidade a longo prazo&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Neste artigo, compartilho as decisões arquiteturais tomadas para garantir uma solução robusta e desacoplada utilizando &lt;strong&gt;Node.js, Clean Architecture, Prisma e Docker&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. O desafio da engenharia
&lt;/h3&gt;

&lt;p&gt;O cenário envolvia complexidades típicas de sistemas que cresceram organicamente ao longo de anos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uma base de dados relacional (SQL) com grande volume de dados e estruturas complexas.&lt;/li&gt;
&lt;li&gt;Necessidade de alta disponibilidade para servir múltiplos clientes simultâneos sem bloquear o Event Loop do Node.js.&lt;/li&gt;
&lt;li&gt;Requisitos estritos de segurança e isolamento total entre ambientes de homologação e produção.&lt;/li&gt;
&lt;li&gt;Infraestrutura na AWS que precisava ser otimizada para eficiência de custos (Compute/Storage).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2. Clean Architecture:
&lt;/h3&gt;

&lt;p&gt;Para garantir a longevidade do projeto, foi adotada a Clean Architecture. O objetivo principal foi isolar as regras de negócio de detalhes de implementação como frameworks web ou drivers de banco de dados.&lt;/p&gt;

&lt;p&gt;A estrutura foi organizada em camadas com responsabilidades definidas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Domain&lt;/strong&gt;: Interfaces e modelos puros da aplicação.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data&lt;/strong&gt;: Casos de uso e regras de negócio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infra&lt;/strong&gt;: Implementações externas (Repositórios, Criptografia, Integrações).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Main&lt;/strong&gt;: Camada de composição que injeta dependências e inicializa o serviço.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essa separação permite, por exemplo, substituir o framework HTTP (ex: Express por Fastify) ou o ORM no futuro com impacto zero na lógica de domínio.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Integração com Bases Existentes (Prisma ORM)
&lt;/h3&gt;

&lt;p&gt;Um dos desafios técnicos era mapear a estrutura de dados pré-existente de forma segura e tipada. Queries manuais tendem a ser frágeis em manutenções futuras.&lt;/p&gt;

&lt;p&gt;A solução foi utilizar o &lt;strong&gt;Prisma ORM&lt;/strong&gt; com sua funcionalidade de &lt;em&gt;Introspection&lt;/em&gt;. Ao invés de gerenciar migrations (que não eram o escopo deste serviço satélite), configurei o Prisma para ler o schema da base existente e gerar a tipagem TypeScript automaticamente.&lt;/p&gt;

&lt;p&gt;Para lidar com tabelas de relacionamento antigas que utilizam chaves compostas em vez de identificadores únicos, utilizei o mapeamento nativo do schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model ExampleRelation {
  userId  Int
  itemId Int

  // Define a identidade única pela combinação das colunas
  @@id([userId, itemId])
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso trouxe &lt;strong&gt;Type Safety&lt;/strong&gt; para o consumo de dados, prevenindo erros de runtime e acelerando o desenvolvimento.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Performance e Eficiência:: Docker Multi-stage e PM2 Cluster
&lt;/h3&gt;

&lt;p&gt;A otimização de infraestrutura foi focada em reduzir o footprint de memória e maximizar o uso de CPU.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker Multi-stage Build&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para evitar imagens pesadas contendo arquivos desnecessários de desenvolvimento, implementei um build em múltiplos estágios usando &lt;strong&gt;Alpine Linux&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Builder Stage&lt;/strong&gt;: Instala todas as dependências, compila o TypeScript e gera os artefatos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runner Stage&lt;/strong&gt;: Copia apenas o código transpilado (&lt;code&gt;dist&lt;/code&gt;) e as dependências de produção.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Resultado&lt;/em&gt;: Imagens finais compactas (cerca de &lt;strong&gt;150MB&lt;/strong&gt;), resultando em deploys mais rápidos e redução de custos de armazenamento no Registry (ECR).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PM2 em Cluster Mode&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Por ser &lt;em&gt;single-threaded&lt;/em&gt;, uma aplicação Node.js padrão utiliza apenas um núcleo do processador, o que pode subutilizar recursos em instâncias de nuvem multi-core.&lt;/p&gt;

&lt;p&gt;A implementação do &lt;strong&gt;PM2 em modo Cluster&lt;/strong&gt; permitiu que a aplicação escalasse verticalmente dentro do container. O gerenciador sobe múltiplos processos (workers) baseados na disponibilidade de CPU, otimizando o throughput. Além da performance, essa estratégia é crucial para resiliência: caso um worker precise reiniciar, o balanceador interno mantém a disponibilidade do serviço redirecionando o tráfego.&lt;/p&gt;

&lt;p&gt;Visão conceitual da arquitetura proposta:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73eqbbzegwkx3lj9ocba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73eqbbzegwkx3lj9ocba.png" alt=" " width="800" height="1422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Imutabilidade e Segurança
&lt;/h3&gt;

&lt;p&gt;Para garantir consistência entre ambientes, implementei uma pipeline de CI/CD baseada em artefatos imutáveis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Um único &lt;code&gt;Dockerfile&lt;/code&gt; é usado para todos os ambientes (Dev, Homol, Prod).&lt;/li&gt;
&lt;li&gt;As variáveis de ambiente sensíveis são injetadas apenas no momento da execução do container.&lt;/li&gt;
&lt;li&gt;Segregação de ambientes via Tags no Registry de containers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Na camada de aplicação, a segurança foi reforçada com middlewares de &lt;strong&gt;CORS estrito&lt;/strong&gt; (permitindo apenas domínios autorizados) e validação de autenticação em todas as rotas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;Este estudo de caso demonstra que é possível aplicar padrões modernos de engenharia de software para modernizar ecossistemas maduros.&lt;/p&gt;

&lt;p&gt;A combinação de &lt;strong&gt;Clean Architecture&lt;/strong&gt; para organização, &lt;strong&gt;Prisma&lt;/strong&gt; para segurança de dados e &lt;strong&gt;Docker/PM2&lt;/strong&gt; para eficiência operacional resultou em um backend sólido, fácil de manter e preparado para escala.&lt;/p&gt;

&lt;p&gt;Gostou do artigo? Conecte-se comigo no &lt;a href="https://www.linkedin.com/in/leonardodumont/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; ou confira meus projetos de código aberto no &lt;a href="https://github.com/leonardopolicarpo/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>node</category>
      <category>aws</category>
      <category>docker</category>
      <category>cleanarchitecture</category>
    </item>
  </channel>
</rss>
