<?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: Marcos Soares</title>
    <description>The latest articles on DEV Community by Marcos Soares (@mrmsoares).</description>
    <link>https://dev.to/mrmsoares</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F588084%2Fb48dd93b-b6a1-4bd7-b8b1-d6c9cd34315d.jpeg</url>
      <title>DEV Community: Marcos Soares</title>
      <link>https://dev.to/mrmsoares</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mrmsoares"/>
    <language>en</language>
    <item>
      <title>Memory Leaks em JavaScript: Diagnóstico, Causas Reais e Correção</title>
      <dc:creator>Marcos Soares</dc:creator>
      <pubDate>Fri, 11 Sep 2026 12:02:55 +0000</pubDate>
      <link>https://dev.to/mrmsoares/memory-leaks-em-javascript-diagnostico-causas-reais-e-correcao-69l</link>
      <guid>https://dev.to/mrmsoares/memory-leaks-em-javascript-diagnostico-causas-reais-e-correcao-69l</guid>
      <description>&lt;p&gt;Um processo Node.js que reinicia sozinho a cada 40 minutos raramente está com bug de lógica. Está com vazamento de memória.&lt;/p&gt;

&lt;p&gt;O sintoma clássico: o container roda liso por meia hora, o &lt;code&gt;heap_size_used&lt;/code&gt; sobe em degraus, o garbage collector começa a rodar com mais frequência (major GC a cada poucos segundos em vez de a cada poucos minutos), a latência p99 dobra e o orquestrador mata o pod com &lt;code&gt;OOMKilled&lt;/code&gt;. Reiniciar resolve. Por 40 minutos.&lt;/p&gt;

&lt;p&gt;Este post é sobre encontrar a causa, não sobre aumentar &lt;code&gt;--max-old-space-size&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como o V8 decide o que é lixo
&lt;/h2&gt;

&lt;p&gt;Existe um mito persistente de que o garbage collector do JavaScript usa contagem de referências. Não usa, e essa confusão faz gente escrever código defensivo inútil.&lt;/p&gt;

&lt;p&gt;O V8 usa &lt;strong&gt;mark-and-sweep&lt;/strong&gt; com alcançabilidade a partir de um conjunto de raízes (GC roots): o objeto global, a pilha de execução atual, closures ativas, e no browser, a árvore do DOM viva. Tudo que não é alcançável a partir dessas raízes vira lixo, independentemente de quantas referências circulares exista entre os objetos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Isto NÃO vaza. Ciclo é irrelevante para mark-and-sweep.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;criarCicloIsolado&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pedido&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cliente&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ana&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;pedido&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cliente&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cliente&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;cliente&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ultimoPedido&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pedido&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// referência circular&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ninguém mais alcança pedido nem cliente&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;criarCicloIsolado&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// Ambos são coletados no próximo major GC.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O heap do V8 é dividido em gerações. Objetos novos nascem na &lt;strong&gt;new space&lt;/strong&gt; (Scavenger, coleta rápida e frequente, tipicamente 1-16 MB). Objetos que sobrevivem a duas coletas são promovidos para a &lt;strong&gt;old space&lt;/strong&gt;, varrida pelo Mark-Compact, que é caro. Um vazamento é, quase sempre, objetos sendo promovidos para old space e nunca liberados de lá.&lt;/p&gt;

&lt;p&gt;Isso importa na prática: se seu vazamento envolve objetos grandes e de vida curta, você não tem vazamento, tem pressão de alocação (aumenta o custo de GC mas o heap estabiliza). Se o &lt;code&gt;heapUsed&lt;/code&gt; após um major GC forçado continua subindo, aí sim é vazamento.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// medir-heap.js — rode com: node --expose-gc medir-heap.js&lt;/span&gt;
&lt;span class="c1"&gt;// --expose-gc é a única forma confiável de medir heap "limpo" sem&lt;/span&gt;
&lt;span class="c1"&gt;// confundir lixo pendente com vazamento real.&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;heapDepoisDoGC&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gc&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// força major GC síncrono&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;heapUsed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;external&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arrayBuffers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;memoryUsage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;heapMB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;heapUsed&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;externalMB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;external&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;arrayBuffersMB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrayBuffers&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;heapDepoisDoGC&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se &lt;code&gt;heapMB&lt;/code&gt; sobe monotonicamente ao longo de 20 amostras sob carga constante, você tem vazamento no heap JavaScript. Se &lt;code&gt;heapMB&lt;/code&gt; fica estável mas o RSS do processo sobe, o vazamento está fora do heap do V8: Buffers, addons nativos, ou fragmentação do alocador.&lt;/p&gt;

&lt;p&gt;Essa distinção entre linguagem e runtime é a mesma que aparece quando se discute &lt;a href="https://dev.to/backend/event-loop-microtasks-macrotasks-modelo-execucao-javascript"&gt;o modelo de execução do JavaScript&lt;/a&gt;: a especificação da linguagem não diz nada sobre GC gerational nem sobre &lt;code&gt;libuv&lt;/code&gt;. Tudo isso é V8 e Node.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  As cinco causas que respondem por quase todo vazamento real
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Listeners que nunca são removidos
&lt;/h3&gt;

&lt;p&gt;O caso mais comum em Node.js e o mais comum em SPAs. Cada &lt;code&gt;addEventListener&lt;/code&gt; ou &lt;code&gt;.on()&lt;/code&gt; cria uma referência forte do emissor para o handler, e do handler para tudo que ele captura no escopo.&lt;/p&gt;




&lt;p&gt;Este é um trecho. O tutorial completo, com todos os exemplos, os testes e as limitações, está em &lt;a href="https://www.vivodecodigo.com.br/backend/memory-leaks-javascript-diagnostico-heap-snapshot-producao" rel="noopener noreferrer"&gt;https://www.vivodecodigo.com.br/backend/memory-leaks-javascript-diagnostico-heap-snapshot-producao&lt;/a&gt;. Se você já passou por esse problema de outro jeito, conta nos comentários: a discussão aqui ajuda a melhorar o artigo.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Engenharia Backend com Node.js e TypeScript: o Guia Definitivo para 2026</title>
      <dc:creator>Marcos Soares</dc:creator>
      <pubDate>Thu, 26 Mar 2026 02:56:53 +0000</pubDate>
      <link>https://dev.to/mrmsoares/engenharia-backend-com-nodejs-e-typescript-o-guia-definitivo-para-2026-271f</link>
      <guid>https://dev.to/mrmsoares/engenharia-backend-com-nodejs-e-typescript-o-guia-definitivo-para-2026-271f</guid>
      <description>&lt;h1&gt;
  
  
  Engenharia Backend com Node.js e TypeScript: O Guia Definitivo para 2026
&lt;/h1&gt;

&lt;p&gt;Depois de duas décadas construindo sistemas web, posso afirmar: Node.js não é apenas hype. É a escolha que te permite dormir tranquilo sabendo que seu sistema processa milhões de requisições sem te acordar às 3h da manhã.&lt;/p&gt;

&lt;p&gt;O ecossistema Node.js amadureceu de forma impressionante em 2026. Temos Prisma 6 revolucionando acesso a dados, TypeScript trazendo sanidade para projetos grandes, e performance que compete com linguagens "tradicionalmente mais rápidas". Mas construir um backend que funciona é fácil. Construir um que escala, é seguro e mantível... isso é engenharia de verdade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por Que Node.js Domina o Backend em 2026
&lt;/h2&gt;

&lt;p&gt;A maioria escolhe Node.js pelos motivos errados: "é JavaScript", "é rápido para prototipar". O verdadeiro poder está na arquitetura event-driven e I/O não-bloqueante. Para aplicações modernas onde o gargalo é I/O (banco, APIs, filesystem), Node.js brilha único.&lt;/p&gt;

&lt;p&gt;Números reais do Vivo de Código:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;324 sinais de tendência processados em tempo real
&lt;/li&gt;
&lt;li&gt;866 entidades no Knowledge Graph com 54K edges&lt;/li&gt;
&lt;li&gt;Pipeline ML com 8 modelos simultâneos&lt;/li&gt;
&lt;li&gt;Response time médio de 89ms&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  O Ecossistema Amadureceu
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;: Padrão da indústria. Type safety sem sacrificar flexibilidade.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prisma&lt;/strong&gt;: Type-safe, migrations automáticas, query optimization inteligente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fastify&lt;/strong&gt;: Performance superior ao Express com melhor DX.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node.js 22+&lt;/strong&gt;: WebStreams nativas, melhor GC, startup 40% mais rápido.&lt;/p&gt;

&lt;h2&gt;
  
  
  Arquitetura Profissional: Separando Amadores de Engenheiros
&lt;/h2&gt;

&lt;p&gt;Não é sobre 15 camadas de abstração. É estrutura que permite evolução, testing e debugging eficientes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/core/application/use-cases/user/create-user.use-case.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateUserUseCase&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;userRepository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserRepository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;passwordHasher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PasswordHasher&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;eventBus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EventBus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CreateUserCommand&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CreateUserResult&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Creating user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Validação de domínio&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existingUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;existingUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserAlreadyExistsError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Criação da entidade&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hashedPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;passwordHasher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hashedPassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Persistência&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Eventos de domínio&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eventBus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publishAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDomainEvents&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;CreateUserResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Camadas da Arquitetura
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Domain Layer&lt;/strong&gt;: Entidades, Value Objects, Domain Services. Lógica de negócio pura.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Application Layer&lt;/strong&gt;: Use Cases, Command/Query handlers. Orquestra operações.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure Layer&lt;/strong&gt;: Repositories, External APIs, Database. Detalhes técnicos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Presentation Layer&lt;/strong&gt;: Controllers, Middlewares, DTOs. Interface com mundo externo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Autenticação e Autorização: Segurança Sem Paranoia
&lt;/h2&gt;

&lt;p&gt;JWT continua sendo padrão, mas implementação importa. Refresh tokens obrigatórios, rotação automática, blacklist para revogação.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/infrastructure/auth/jwt-auth.service.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JwtAuthService&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;generateTokenPair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TokenPair&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;access&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jwtService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;15m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;issuer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;issuer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;audience&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audience&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jwtService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;refresh&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;7d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;refreshSecret&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Armazena refresh token com TTL automático&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`refresh_token:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;604800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 7 dias&lt;/span&gt;
      &lt;span class="nx"&gt;refreshToken&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;accessToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refreshToken&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementação de RBAC
&lt;/h3&gt;

&lt;p&gt;Role-Based Access Control com hierarquia de permissões. Middleware que verifica não apenas autenticação, mas autorização granular por recurso.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance e Caching: A Diferença Entre Funcionar e Escalar
&lt;/h2&gt;

&lt;p&gt;Caching em múltiplas camadas: Redis para sessões, CDN para assets, query caching no Prisma, HTTP caching com ETags.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redis Strategies&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cache-aside para dados frequentes&lt;/li&gt;
&lt;li&gt;Write-through para dados críticos
&lt;/li&gt;
&lt;li&gt;Pub/sub para invalidação distribuída&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Database Optimization&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connection pooling inteligente&lt;/li&gt;
&lt;li&gt;Query optimization automática&lt;/li&gt;
&lt;li&gt;Read replicas para consultas pesadas&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Observabilidade: Enxergando o Invisível
&lt;/h2&gt;

&lt;p&gt;Logs estruturados com Pino, métricas com Prometheus, tracing distribuído com OpenTelemetry. Não é sobre coletar dados, é sobre ter insights acionáveis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Health Checks Inteligentes&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Liveness: processo está rodando?&lt;/li&gt;
&lt;li&gt;Readiness: pode receber tráfego?
&lt;/li&gt;
&lt;li&gt;Startup: inicialização completa?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testes: Confiança Para Deploy Sexta-feira
&lt;/h2&gt;

&lt;p&gt;Pirâmide de testes equilibrada: muitos unit tests, alguns integration tests, poucos e2e tests. TDD não é religião, é ferramenta para design melhor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test Containers&lt;/strong&gt; para integration tests com dependências reais. &lt;strong&gt;Supertest&lt;/strong&gt; para testes de API. &lt;strong&gt;Jest&lt;/strong&gt; configurado para performance máxima.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy e DevOps: Da Máquina Local Para Produção
&lt;/h2&gt;

&lt;p&gt;Docker multi-stage builds, Kubernetes com auto-scaling, CI/CD com zero-downtime deployments. Blue-green deployments para releases críticas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monitoring de Produção&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;APM para performance&lt;/li&gt;
&lt;li&gt;Error tracking para bugs&lt;/li&gt;
&lt;li&gt;Business metrics para impacto&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Leia o artigo completo com todos os exemplos de código e diagramas em &lt;a href="https://vivodecodigo.com.br/backend/engenharia-backend-nodejs-typescript-guia-definitivo" rel="noopener noreferrer"&gt;https://vivodecodigo.com.br/backend/engenharia-backend-nodejs-typescript-guia-definitivo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>engenharia</category>
      <category>backend</category>
      <category>node</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Anatomia do Vivo de Codigo: Como Construi um Blog com Stack de Startup</title>
      <dc:creator>Marcos Soares</dc:creator>
      <pubDate>Thu, 26 Mar 2026 02:48:31 +0000</pubDate>
      <link>https://dev.to/mrmsoares/anatomia-do-vivo-de-codigo-como-construi-um-blog-com-stack-de-startup-2idj</link>
      <guid>https://dev.to/mrmsoares/anatomia-do-vivo-de-codigo-como-construi-um-blog-com-stack-de-startup-2idj</guid>
      <description>&lt;h1&gt;
  
  
  Como Construí um Blog com Arquitetura de Startup Unicórnio por $0/mês
&lt;/h1&gt;

&lt;p&gt;Depois de 21 anos construindo sistemas, criei um blog que publica posts sozinho usando ML, knowledge graph e pipeline automatizado. Por que alguém faria isso ao invés de usar WordPress?&lt;/p&gt;

&lt;p&gt;Este é o decision log completo da arquitetura do Vivo de Código: Next.js 16, PostgreSQL com pgvector, 10 containers Docker na Oracle Cloud e um sistema que parece saído de uma startup de $1B rodando com custo zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Arquitetura Geral
&lt;/h2&gt;



&lt;pre data-lang="mermaid"&gt;&lt;code&gt;graph TB
    subgraph "Frontend (Vercel)"
        A[Next.js 16 + React 19]
        A --&amp;gt; D[6 Cron Jobs Proxy]
    end

    subgraph "Database (Supabase)"
        E[PostgreSQL + pgvector]
        E --&amp;gt; F[Embeddings 384-dim]
        E --&amp;gt; G[Knowledge Graph]
    end

    subgraph "VPS Oracle Cloud"
        I[10 Docker Containers]
        I --&amp;gt; J[ACI - FastAPI]
        I --&amp;gt; K[MinIO Storage]
        I --&amp;gt; L[12 Python Crons]
    end

    A --&amp;gt; E
    A --&amp;gt; I
    J --&amp;gt; E&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Esta arquitetura serve 27 posts, ~2.000 palavras cada, com pipeline de ML que roda embeddings, extrai entidades e constrói grafos de conhecimento automaticamente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por Que Next.js 16 e Não Astro/Hugo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Alternativas consideradas:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Astro (melhor performance)
&lt;/li&gt;
&lt;li&gt;Hugo (velocidade insana)&lt;/li&gt;
&lt;li&gt;WordPress (ecossistema gigante)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Por que Next.js venceu:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server Components:&lt;/strong&gt; Posso rodar ML direto no servidor. O Revenue Router do AdSense segmenta anúncios por perfil sem API calls.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ISR + On-Demand Revalidation:&lt;/strong&gt; Pipeline publica post → webhook revalida páginas específicas. Zero rebuild manual.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexibilidade:&lt;/strong&gt; Páginas estáticas (posts), dinâmicas (busca) e híbridas (comentários) na mesma stack.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Números reais:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build: ~2min para 27 posts&lt;/li&gt;
&lt;li&gt;FCP: ~0.8s
&lt;/li&gt;
&lt;li&gt;TTI: ~1.2s&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  PostgreSQL + pgvector: O Cérebro do Sistema
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Por que não MongoDB/Redis/Elasticsearch:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PostgreSQL resolve tudo: dados relacionais, embeddings vetoriais, full-text search e JSON. Um banco, múltiplas funções.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Busca semântica com pgvector&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; 
  &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;query_embedding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;similarity&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;query_embedding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;query_embedding&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;O pipeline de embeddings:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Post publicado → webhook dispara&lt;/li&gt;
&lt;li&gt;Texto chunked em 512 tokens
&lt;/li&gt;
&lt;li&gt;all-MiniLM-L6-v2 gera embeddings 384-dim&lt;/li&gt;
&lt;li&gt;pgvector indexa para busca semântica&lt;/li&gt;
&lt;li&gt;Knowledge graph extrai entidades relacionadas&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Custo:&lt;/strong&gt; $0 (Supabase free tier: 500MB, 2 conexões simultâneas)&lt;/p&gt;

&lt;h2&gt;
  
  
  VPS Oracle Cloud: 10 Containers por $0
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Por que Oracle Cloud e não AWS/GCP:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Oracle Always Free: 4 OCPUs ARM, 24GB RAM, 200GB storage. Para sempre. Sem cartão de crédito após trial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Os 10 containers rodando:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml (resumido)&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;aci-api&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vivodecodigo/aci:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8000:8000"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="na"&gt;minio&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;minio/minio&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./data:/data"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="na"&gt;ml-pipeline&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vivodecodigo/ml-pipeline:latest&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;SUPABASE_URL=${SUPABASE_URL}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;HUGGINGFACE_TOKEN=${HF_TOKEN}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;12 Python crons rodando:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scraping de fontes RSS (4x/dia)&lt;/li&gt;
&lt;li&gt;Processamento de embeddings (1x/dia)
&lt;/li&gt;
&lt;li&gt;Backup automático (1x/semana)&lt;/li&gt;
&lt;li&gt;Health checks (1x/hora)&lt;/li&gt;
&lt;li&gt;Analytics sync (1x/dia)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pipeline de ML sem GPU
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;O desafio:&lt;/strong&gt; Rodar modelos Transformer em CPU ARM sem explodir o orçamento.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A solução:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sentence-transformers otimizado para CPU&lt;/li&gt;
&lt;li&gt;Batch processing noturno
&lt;/li&gt;
&lt;li&gt;Cache agressivo de embeddings&lt;/li&gt;
&lt;li&gt;Quantização INT8 nos modelos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tempo de processamento:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 post (~2000 palavras): ~45s&lt;/li&gt;
&lt;li&gt;Batch 10 posts: ~6min&lt;/li&gt;
&lt;li&gt;Embedding similarity search: ~50ms&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Knowledge Graph Caseiro
&lt;/h2&gt;

&lt;p&gt;Cada post vira um nó conectado por:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Similaridade semântica (embeddings)&lt;/li&gt;
&lt;li&gt;Tags compartilhadas&lt;/li&gt;
&lt;li&gt;Entidades nomeadas (spaCy)&lt;/li&gt;
&lt;li&gt;Referências cruzadas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Resultado: sistema de recomendação que sugere posts relacionados com 78% de precisão vs 23% de tags manuais.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoramento e Analytics
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Stack de observabilidade:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Umami (analytics privacy-first)&lt;/li&gt;
&lt;li&gt;Sentry (error tracking)
&lt;/li&gt;
&lt;li&gt;Uptime Robot (monitoring)&lt;/li&gt;
&lt;li&gt;Custom dashboards (Grafana + Prometheus)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Métricas que importam:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tempo de leitura médio: 4min 32s&lt;/li&gt;
&lt;li&gt;Taxa de rejeição: 23%
&lt;/li&gt;
&lt;li&gt;Posts mais lidos: tutoriais práticos&lt;/li&gt;
&lt;li&gt;Horário de pico: 14h-16h (Brasil)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Custos Reais Mensais
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vercel:&lt;/strong&gt; $0 (hobby plan)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supabase:&lt;/strong&gt; $0 (free tier)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Oracle Cloud:&lt;/strong&gt; $0 (always free)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare:&lt;/strong&gt; $0 (free tier)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domínio:&lt;/strong&gt; R$ 40/ano&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total mensal:&lt;/strong&gt; ~R$ 3,33&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lições Aprendidas
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Over-engineering vale a pena&lt;/strong&gt; quando cada decisão vira conhecimento aplicável em projetos pagos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Free tiers são poderosos&lt;/strong&gt; se você conhece os limites e otimiza dentro deles.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automação é investimento&lt;/strong&gt; - 40h construindo pipeline vs 2h/semana publicando manualmente.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;PostgreSQL é subestimado&lt;/strong&gt; - um banco que faz trabalho de 4 ferramentas.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;O Vivo de Código não é só um blog. É um laboratório de produção onde testo tecnologias que uso com clientes, sem o risco de quebrar sistemas críticos.&lt;/p&gt;

&lt;p&gt;Leia o artigo completo com todos os exemplos de código e diagramas em &lt;a href="https://vivodecodigo.com.br/backend/anatomia-vivo-de-codigo-arquitetura-blog-tech" rel="noopener noreferrer"&gt;https://vivodecodigo.com.br/backend/anatomia-vivo-de-codigo-arquitetura-blog-tech&lt;/a&gt;&lt;/p&gt;

</description>
      <category>anatomia</category>
      <category>vivo</category>
      <category>codigo</category>
      <category>construi</category>
    </item>
  </channel>
</rss>
