<?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: Flávio Luiz</title>
    <description>The latest articles on DEV Community by Flávio Luiz (@flaviolzsantos).</description>
    <link>https://dev.to/flaviolzsantos</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%2F2472986%2Ffbb6dd99-d4ab-4efc-8518-10b4d11b40a6.jpeg</url>
      <title>DEV Community: Flávio Luiz</title>
      <link>https://dev.to/flaviolzsantos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/flaviolzsantos"/>
    <language>en</language>
    <item>
      <title>Monitoring na prática: olhando além do “o sistema está no ar”</title>
      <dc:creator>Flávio Luiz</dc:creator>
      <pubDate>Fri, 03 Oct 2025 02:28:17 +0000</pubDate>
      <link>https://dev.to/flaviolzsantos/monitoring-na-pratica-olhando-alem-do-o-sistema-esta-no-ar-30me</link>
      <guid>https://dev.to/flaviolzsantos/monitoring-na-pratica-olhando-alem-do-o-sistema-esta-no-ar-30me</guid>
      <description>&lt;p&gt;Quando falamos de monitoramento, não basta saber se o site responde. É preciso entender como ele responde, para quem, em que condições e com que riscos.&lt;/p&gt;

&lt;p&gt;Vamos quebrar isso em camadas, com exemplos de um marketplace em produção:&lt;/p&gt;

&lt;h2&gt;
  
  
  🔍 Health Monitoring
&lt;/h2&gt;

&lt;p&gt;Checar se os serviços estão vivos.&lt;br&gt;
➡Exemplo prático: rodar health checks automáticos a cada 30 segundos no serviço de pagamentos. Se ele parar de responder, o load balancer remove a instância para não impactar novos clientes.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌐 Availability Monitoring
&lt;/h2&gt;

&lt;p&gt;É diferente de “estar no ar”: significa estar realmente acessível para o usuário.&lt;br&gt;
➡ Exemplo prático: o checkout está online, mas 20% dos usuários do Nordeste não conseguem acessá-lo por problemas de rota em um provedor de internet local. Um monitor de disponibilidade global detecta a falha de rede e aciona fallback para outro provedor de CDN.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ Performance Monitoring
&lt;/h2&gt;

&lt;p&gt;Não é só uptime: é tempo de resposta e consumo de recursos.&lt;br&gt;
➡ Exemplo prático: durante a Black Friday, o endpoint /search começa a responder em 4 segundos em vez de 500ms. O time recebe alerta no DataDog, analisa traces no OpenTelemetry e descobre que a query no banco perdeu o índice após um deploy.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔒 Security Monitoring
&lt;/h2&gt;

&lt;p&gt;Monitorar não só ataques externos, mas também anomalias internas.&lt;br&gt;
➡ Exemplo prático: um padrão de chamadas para /login com milhares de tentativas por minuto indica um ataque de credential stuffing. O monitor de segurança dispara um alerta e aciona automaticamente bloqueio via WAF e reCAPTCHA.&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 Usage Monitoring
&lt;/h2&gt;

&lt;p&gt;Mede comportamento real do usuário e impacto no negócio.&lt;br&gt;
➡ Exemplo prático: métricas mostram que 60% dos usuários abandonam o carrinho ao adicionar mais de 5 itens. Com isso, o time percebe que a UX da tela de resumo está confusa e ajusta o fluxo.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Instrumentation
&lt;/h2&gt;

&lt;p&gt;Colocar métricas e logs no código de forma planejada.&lt;br&gt;
➡ Exemplo prático: o serviço de pedidos emite métricas para cada evento: pedido_criado, pedido_pago, pedido_cancelado. Isso permite construir funis no dashboard e entender onde os usuários travam.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚨 Visualization &amp;amp; Alerts
&lt;/h2&gt;

&lt;p&gt;É a forma como o time consome os dados de monitoramento.&lt;br&gt;
➡ Exemplo prático: dashboards no Grafana mostram latência, throughput e taxa de erros em tempo real. Alertas no Slack/Teams são configurados com thresholds dinâmicos (ex.: erro &amp;gt; 2% por 5 minutos) para evitar falsos positivos.&lt;/p&gt;




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

&lt;p&gt;Monitoramento é como cuidar da saúde de uma pessoa: não basta medir a pressão, é preciso olhar coração, respiração, comportamento e sinais de alerta.&lt;br&gt;
No mundo dos sistemas, é o que garante confiança, escalabilidade e segurança.&lt;/p&gt;

&lt;p&gt;👉 &lt;em&gt;E aí: no seu time vocês já têm monitoramento distribuído (com traces, métricas e logs) ou ainda dependem de “alguém avisar que deu erro”?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>monitoring</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Como a comunicação na Web realmente funciona (com exemplos práticos e simples)</title>
      <dc:creator>Flávio Luiz</dc:creator>
      <pubDate>Fri, 03 Oct 2025 02:01:35 +0000</pubDate>
      <link>https://dev.to/flaviolzsantos/como-a-comunicacao-na-web-realmente-funciona-com-exemplos-praticos-e-simples-2c4o</link>
      <guid>https://dev.to/flaviolzsantos/como-a-comunicacao-na-web-realmente-funciona-com-exemplos-praticos-e-simples-2c4o</guid>
      <description>&lt;p&gt;Quando você entra em um site de marketplace para comprar um tênis, muita coisa acontece por trás da tela. Existe uma verdadeira “conversa” entre computadores e servidores para que a página carregue, o preço apareça e o pedido seja processado. Essa conversa é a comunicação na web.&lt;/p&gt;

&lt;p&gt;Quero explicar de forma simples alguns conceitos que usamos no dia a dia do desenvolvimento de software: HTTP, TCP, UDP, RPC, gRPC, REST e GraphQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  TCP e UDP: o alicerce da conversa
&lt;/h2&gt;

&lt;p&gt;Pense que a internet é como uma estrada. Para mandar informações, precisamos de regras de trânsito. É aqui que entram o TCP e o UDP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;TCP (Transmission Control Protocol):&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
É como enviar um produto por correio com aviso de recebimento. O servidor confirma cada pacote de dados que chegou. Isso garante segurança e ordem, mas pode ser mais lento.&lt;br&gt;
 → Exemplo no marketplace: quando você confirma a compra, não dá pra perder nenhuma informação do cartão de crédito. O TCP garante que tudo chegue certinho.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;UDP (User Datagram Protocol):&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
É como mandar uma mensagem de voz no WhatsApp: se perder um pedacinho, segue o baile. Ele é mais rápido porque não confirma cada entrega.&lt;br&gt;
 → Exemplo no marketplace: se houver um sistema de recomendação em tempo real ou uma transmissão ao vivo de um vendedor, o UDP pode ser usado. Melhor receber algo rápido do que perfeito.&lt;/p&gt;
&lt;h2&gt;
  
  
  RPC e gRPC: pedindo favores
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;RPC (Remote Procedure Call)&lt;/strong&gt;&lt;/em&gt; é como ligar para um amigo e pedir:&lt;br&gt;
“Cara, pode rodar aquela função pra mim aí no seu computador e me passar o resultado?”.&lt;br&gt;
No mundo web, RPC é isso: chamar métodos em outro sistema como se fossem locais.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;gRPC (Google Remote Procedure Call)&lt;/strong&gt;&lt;/em&gt; é uma versão moderna desse conceito. Ele é super eficiente, usa HTTP/2 e transmite dados em binário (Protobuf), em vez de texto.&lt;br&gt;
→ Exemplo no marketplace: quando o app precisa verificar em milissegundos se um produto ainda está no estoque, gRPC é ótimo porque é rápido e econômico.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;REST: o clássico que todo mundo usa&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;O REST é um estilo de comunicação baseado no HTTP. Ele trata cada recurso (produto, pedido, cliente) como uma URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /produtos/123 → Buscar o produto de id 123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /pedidos → Criar um novo pedido
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;GraphQL: perguntando só o que precisa&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O GraphQL nasceu para resolver um problema do REST: o excesso ou falta de dados.&lt;br&gt;
Imagine que a página do tênis precisa do nome, preço e cor.&lt;/p&gt;

&lt;p&gt;No REST, você provavelmente recebe muito mais informação do que precisa (descrição, avaliações, imagens etc).&lt;/p&gt;

&lt;p&gt;No GraphQL, você faz uma única query pedindo só o que quer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  produto(id: "123") {
    nome
    preco
    cor
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;No fundo, todos esses protocolos e estilos são diferentes formas de resolver o mesmo problema: como dois sistemas trocam informações de maneira eficiente e confiável.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;TCP/UDP → base da comunicação&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;HTTP → idioma padrão da web&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;RPC/gRPC → chamadas rápidas e diretas&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;REST → clássico e simples&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;GraphQL → sob medida, sem desperdício&lt;/em&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>beginners</category>
      <category>networking</category>
    </item>
    <item>
      <title>[BD] História 4: Lory e o Uso de Cache com Go</title>
      <dc:creator>Flávio Luiz</dc:creator>
      <pubDate>Thu, 28 Nov 2024 01:13:49 +0000</pubDate>
      <link>https://dev.to/flaviolzsantos/bd-historia-4-lory-e-o-uso-de-cache-com-go-fa6</link>
      <guid>https://dev.to/flaviolzsantos/bd-historia-4-lory-e-o-uso-de-cache-com-go-fa6</guid>
      <description>&lt;p&gt;&lt;strong&gt;O Desafio da Performance no E-commerce&lt;/strong&gt;&lt;br&gt;
Lory, uma programadora dedicada, teve mais uma ideia para melhorar a performance do ecommerce, fazer o uso de cache. Tabelas como Order, Customer, Invoice e Product acumularam milhões de registros, e as consultas começaram a sofrer com lentidão. Lory sabia que precisava agir para otimizar o desempenho e garantir uma experiência fluida para os usuários.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Solução com Cache&lt;/strong&gt;&lt;br&gt;
Lory decidiu implementar um sistema de cache usando Redis, uma ferramenta popular que armazena dados em memória para respostas rápidas. Em vez de consultar o banco de dados diretamente, os resultados frequentemente acessados seriam armazenados em cache.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Implementação em Go&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lory usou a biblioteca go-redis para interagir com o Redis.&lt;br&gt;
Configuração do Redis: Primeiro, ela configurou o cliente Redis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import (
    "context"
    "github.com/redis/go-redis/v9"
)
var ctx = context.Background()
func newRedisClient() *redis.Client {
    return redis.NewClient(&amp;amp;redis.Options{
        Addr: "localhost:6379",
    })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Consulta com Cache: Depois, ela implementou uma função para buscar pedidos de um cliente. Se os dados estivessem em cache, eram retornados rapidamente. Caso contrário, a consulta seria feita no banco, e os dados armazenados em cache.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Order struct {
    OrderID    int
    CustomerID int
    OrderDate  string
    Amount     float64
}
func getOrdersByCustomer(redisClient *redis.Client, customerId int) ([]Order, error) {
    cacheKey := fmt.Sprintf("orders:%d", customerId)

    // Tenta buscar no cache
    cachedOrders, err := redisClient.Get(ctx, cacheKey).Result()
    if err == nil {
        // Deserializa os pedidos do cache
        var orders []Order
        json.Unmarshal([]byte(cachedOrders), &amp;amp;orders)
        return orders, nil
    }

    // Se não estiver no cache, consulta no banco de dados (simulação)
    orders := []Order{
        {OrderID: 1, CustomerID: customerId, OrderDate: "2024-11-01", Amount: 150.00},
    }

    // Salva os resultados no cache
    data, _ := json.Marshal(orders)
    redisClient.Set(ctx, cacheKey, data, 3600*time.Second)
    return orders, nil
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Benefícios e Limitações do Cache&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Benefícios:&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resposta Rápida: Dados em cache são retornados em milissegundos.&lt;/li&gt;
&lt;li&gt;Redução de Carga no Banco: Menos consultas diretas ao banco liberam recursos para outras operações.&lt;/li&gt;
&lt;li&gt;Escalabilidade: Suporta mais usuários simultaneamente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Limitações:&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dados Desatualizados: Alterações no banco podem não ser refletidas imediatamente no cache.&lt;/li&gt;
&lt;li&gt;Consumo de Memória: Armazenar grandes volumes de dados no Redis pode sobrecarregar os recursos.&lt;/li&gt;
&lt;li&gt;Complexidade de Implementação: Exige planejamento para garantir que o cache seja sincronizado corretamente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Lições Aprendidas&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cache Não É a Solução Definitiva: Deve complementar, não substituir, otimizações no banco.&lt;/li&gt;
&lt;li&gt;Garantir dados atualizados: Criar estratégias para garantir que os dados no cache estejam sempre atualizados conforme as regras de negócio.&lt;/li&gt;
&lt;li&gt;Monitoramento Contínuo: Ferramentas como Prometheus ajudaram Lory a identificar gargalos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusão&lt;/strong&gt;&lt;br&gt;
A jornada de Lory mostra que melhorar a performance no banco de dados é um processo contínuo. Com cache, views, particionamento e processamento assíncrono, ela transformou o sistema em uma plataforma escalável e eficiente, pronta para crescer junto com o negócio.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>[BD] História 3: Lory e a Desnormalização no Sistema de E-commerce</title>
      <dc:creator>Flávio Luiz</dc:creator>
      <pubDate>Thu, 28 Nov 2024 00:18:05 +0000</pubDate>
      <link>https://dev.to/flaviolzsantos/historia-3-lory-e-a-desnormalizacao-no-sistema-de-e-commerce-18jc</link>
      <guid>https://dev.to/flaviolzsantos/historia-3-lory-e-a-desnormalizacao-no-sistema-de-e-commerce-18jc</guid>
      <description>&lt;p&gt;Nessa história, vamos abordar temas de Desnormalização de um banco de dados&lt;/p&gt;

&lt;p&gt;Lory continuou com problemas de performance no banco de dados, dessa vez ela foi ousada e resolveu fazer uma desnormalização de algumas tabelas para melhorar a performance. Inicialmente, a aplicação usava um modelo normalizado com tabelas para Ordem, Pedido, Cliente e NotaFiscal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consultas lentas em horários de pico.&lt;/strong&gt;&lt;br&gt;
Relatórios demorados, afetando as decisões estratégicas.&lt;br&gt;
Sobrecarregamento do banco de dados, prejudicando integrações como o ERP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Desnormalização como uma possível Solução&lt;/strong&gt;&lt;br&gt;
Lory percebeu que muitas das consultas mais lentas envolviam joins complexos entre tabelas grandes. Por exemplo, um relatório básico de pedidos por cliente demorava vários minutos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT 
    c.ClienteID,
    c.Nome AS Cliente,
    COUNT(p.PedidoID) AS TotalPedidos,
    SUM(o.Quantidade * o.Preco) AS ValorTotal,
    MAX(nf.DataEmissao) AS UltimaNotaFiscal
FROM Cliente c
JOIN Pedido p ON c.ClienteID = p.ClienteID
JOIN Ordem o ON p.PedidoID = o.PedidoID
JOIN NotaFiscal nf ON p.PedidoID = nf.PedidoID
GROUP BY c.ClienteID, c.Nome;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lory decidiu desnormalizar os dados, criando uma tabela que consolidava as informações frequentemente consultadas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE ResumoPedidos (
    ClienteID INT,
    Nome VARCHAR(100),
    TotalPedidos INT,
    ValorTotal DECIMAL(18, 2),
    UltimaNotaFiscal DATE
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E preencheu os dados com uma query agendada periodicamente, um cron que rodava 1x por dia e executava a seguinte query em Postgre:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INSERT INTO ResumoPedidos
SELECT 
    c.ClienteID,
    c.Nome,
    COUNT(p.PedidoID),
    SUM(o.Quantidade * o.Preco),
    MAX(nf.DataEmissao)
FROM Cliente c
JOIN Pedido p ON c.ClienteID = p.ClienteID
JOIN Ordem o ON p.PedidoID = o.PedidoID
JOIN NotaFiscal nf ON p.PedidoID = nf.PedidoID
WHERE p.DtCriacao = CURRENT_DATE - INTERVAL '1 day'
GROUP BY c.ClienteID, c.Nome;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Obs. Os requisitos permitiam esse cenário, mas poderia ser em qualquer período, isso pode variar por necessidade de negócio.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resultados da Desnormalização&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;&lt;strong&gt;Consultas mais rápidas&lt;/strong&gt;&lt;/em&gt;: Dados consolidados reduziram o tempo de execução de queries de minutos para segundos.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;strong&gt;Relatórios instantâneos&lt;/strong&gt;&lt;/em&gt;: Relatórios complexos tornaram-se viáveis em tempo real.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;strong&gt;Integração facilitada&lt;/strong&gt;&lt;/em&gt;: O ERP agora consumia dados da tabela desnormalizada, diminuindo sua dependência de joins pesados.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Limitações da Desnormalização&lt;/strong&gt;&lt;br&gt;
Apesar das melhorias, Lory enfrentou alguns desafios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;&lt;strong&gt;Manutenção Complexa&lt;/strong&gt;&lt;/em&gt;: Alterar os dados exigia sincronizar tabelas normalizadas e desnormalizadas.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;strong&gt;Armazenamento Adicional&lt;/strong&gt;&lt;/em&gt;: Dados duplicados aumentaram o consumo de espaço.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;&lt;strong&gt;Dados Desatualizados&lt;/strong&gt;&lt;/em&gt;: Se o processo de atualização falhasse, os relatórios poderiam apresentar informações inconsistentes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Aprendizados&lt;/strong&gt;&lt;br&gt;
Quando a Desnormalização é Necessária&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A desnormalização é útil quando o sistema enfrenta gargalos de performance devido a joins complexos em tabelas grandes.&lt;/li&gt;
&lt;li&gt;É indicada em cenários onde a velocidade de leitura é mais importante que a consistência perfeita dos dados.&lt;/li&gt;
&lt;li&gt;Consultas complexas envolvendo várias tabelas (como JOIN e agregações) podem ser otimizadas armazenando dados consolidados em tabelas desnormalizadas.&lt;/li&gt;
&lt;li&gt;O armazenamento de dados pré-calculados reduz o tempo de execução de queries frequentes, tornando o sistema mais responsivo.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>[BD] História 2: Lory e a Criação de Views no Sistema de E-commerce</title>
      <dc:creator>Flávio Luiz</dc:creator>
      <pubDate>Tue, 26 Nov 2024 13:16:10 +0000</pubDate>
      <link>https://dev.to/flaviolzsantos/historia-2-lory-e-a-criacao-de-views-no-sistema-de-e-commerce-4447</link>
      <guid>https://dev.to/flaviolzsantos/historia-2-lory-e-a-criacao-de-views-no-sistema-de-e-commerce-4447</guid>
      <description>&lt;p&gt;Nessa história, vamos abordar temas de Views de um banco de dados&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O Crescimento do Sistema&lt;/strong&gt;&lt;br&gt;
Depois de solucionar os problemas de performance com indexação, Lory viu o e-commerce prosperar. Porém, como todo sistema em crescimento, novos desafios surgiram. Os lojistas começaram a solicitar relatórios mais detalhados, como pedidos consolidados por cliente, produtos mais vendidos e informações fiscais. Além disso, a integração com o ERP da empresa tornou-se essencial para automatizar processos.&lt;/p&gt;

&lt;p&gt;Essas novas demandas sobrecarregaram o sistema. Consultas complexas que uniam tabelas como Ordem, Pedido, Cliente e NotaFiscal começaram a impactar a performance. Relatórios que deveriam ser gerados em minutos passaram a levar horas, afetando o atendimento aos lojistas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O Problema de Performance&lt;/strong&gt;&lt;br&gt;
Lory percebeu que o gargalo estava nas consultas que uniam grandes tabelas. Uma das queries problemáticas era:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT 
    c.ClienteID,
    c.Nome AS Cliente,
    COUNT(p.PedidoID) AS TotalPedidos,
    SUM(o.Quantidade * o.Preco) AS ValorTotal,
    MAX(nf.DataEmissao) AS UltimaNotaFiscal
FROM Cliente c
JOIN Pedido p ON c.ClienteID = p.ClienteID
JOIN Ordem o ON p.PedidoID = o.PedidoID
JOIN NotaFiscal nf ON p.PedidoID = nf.PedidoID
GROUP BY c.ClienteID, c.Nome;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa consulta fazia leituras demoradas nas tabelas e consumia muitos recursos do banco de dados, especialmente em horários de pico.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Solução com Views&lt;/strong&gt;&lt;br&gt;
Lory encontrou a solução nas views do banco de dados. Ela percebeu que poderia criar uma estrutura pré-processada para consolidar os dados frequentemente utilizados, reduzindo o tempo de execução das consultas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Criação da View&lt;/strong&gt;&lt;br&gt;
Lory criou uma view para consolidar as informações mais usadas pelos relatórios e pelo ERP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE VIEW vw_ResumoPedidos AS
SELECT 
    c.ClienteID,
    c.Nome AS Cliente,
    COUNT(p.PedidoID) AS TotalPedidos,
    SUM(o.Quantidade * o.Preco) AS ValorTotal,
    MAX(nf.DataEmissao) AS UltimaNotaFiscal
FROM Cliente c
JOIN Pedido p ON c.ClienteID = p.ClienteID
JOIN Ordem o ON p.PedidoID = o.PedidoID
JOIN NotaFiscal nf ON p.PedidoID = nf.PedidoID
GROUP BY c.ClienteID, c.Nome;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, em vez de executar a consulta diretamente nas tabelas, o sistema poderia acessar a view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM vw_ResumoPedidos WHERE ClienteID = 12345;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;O Resultado&lt;/strong&gt;&lt;br&gt;
Com a criação da view:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consultas complexas que antes levavam minutos agora eram respondidas em segundos.&lt;/li&gt;
&lt;li&gt;Relatórios passaram a ser gerados mais rapidamente.&lt;/li&gt;
&lt;li&gt;A integração com o ERP foi simplificada, pois o sistema podia acessar dados consolidados diretamente na view.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;As Limitações e os Novos Desafios&lt;/strong&gt;&lt;br&gt;
Apesar do sucesso inicial, Lory percebeu algumas limitações no uso de views:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Problemas Identificados&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Views Não Indexadas: Consultas em views sem índices eram lentas em tabelas muito grandes.&lt;/li&gt;
&lt;li&gt;Manutenção Difícil: Alterações nas tabelas base exigiam que Lory ajustasse a lógica da view.&lt;/li&gt;
&lt;li&gt;Uso de Recursos: Views complexas consumiam muitos recursos do banco de dados em horários de alta demanda.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;O Impacto na Integração com o ERP&lt;/strong&gt;&lt;br&gt;
Ao integrar o sistema com o ERP, o volume de dados acessado aumentou ainda mais. O ERP dependia da view para consolidar informações, e em horários de pico, as consultas começaram a afetar novamente o desempenho geral do sistema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Solução para Escalabilidade&lt;/strong&gt;&lt;br&gt;
Lory sabia que precisava otimizar ainda mais o sistema. Ela implementou as seguintes melhorias:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1. Views Materializadas&lt;/em&gt;&lt;br&gt;
Para evitar que a view recalculasse os dados a cada consulta, Lory criou uma view materializada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE MATERIALIZED VIEW mv_ResumoPedidos AS
SELECT 
    c.ClienteID,
    c.Nome AS Cliente,
    COUNT(p.PedidoID) AS TotalPedidos,
    SUM(o.Quantidade * o.Preco) AS ValorTotal,
    MAX(nf.DataEmissao) AS UltimaNotaFiscal
FROM Cliente c
JOIN Pedido p ON c.ClienteID = p.ClienteID
JOIN Ordem o ON p.PedidoID = o.PedidoID
JOIN NotaFiscal nf ON p.PedidoID = nf.PedidoID
GROUP BY c.ClienteID, c.Nome;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A view materializada armazenava os dados pré-calculados, reduzindo o custo das consultas subsequentes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2. Atualizações Periódicas&lt;/em&gt;&lt;br&gt;
Para manter os dados da view atualizados, ela configurou um processo periódico:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REFRESH MATERIALIZED VIEW mv_ResumoPedidos;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Lições Aprendidas&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Views Simplificam Consultas: Consolidar dados com views reduz o tempo de execução de consultas complexas.&lt;/li&gt;
&lt;li&gt;Manutenção Regular é Essencial: Views materializadas precisam de atualizações periódicas para garantir dados consistentes.&lt;/li&gt;
&lt;li&gt;Equilíbrio entre Simplicidade e Performance: Soluções como views materializadas e particionamento exigem planejamento para evitar complexidade excessiva.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Com essas melhorias, o sistema de Lory tornou-se mais escalável e capaz de suportar o crescimento do e-commerce e a integração com o ERP. Os lojistas estavam felizes, e Lory continuava a aprender e aplicar novas estratégias para enfrentar desafios futuros.&lt;/p&gt;

&lt;p&gt;Referencias&lt;br&gt;
&lt;a href="https://www.postgresql.org/docs/current/sql-refreshmaterializedview.html" rel="noopener noreferrer"&gt;https://www.postgresql.org/docs/current/sql-refreshmaterializedview.html&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.postgresql.org/docs/17/sql-creatematerializedview.html" rel="noopener noreferrer"&gt;https://www.postgresql.org/docs/17/sql-creatematerializedview.html&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.postgresql.org/docs/17/sql-createview.html" rel="noopener noreferrer"&gt;https://www.postgresql.org/docs/17/sql-createview.html&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>[BD] História 1: A Jornada de Lory e a Indexação</title>
      <dc:creator>Flávio Luiz</dc:creator>
      <pubDate>Mon, 25 Nov 2024 17:31:08 +0000</pubDate>
      <link>https://dev.to/flaviolzsantos/historia-1-a-jornada-de-lory-e-a-indexacao-2led</link>
      <guid>https://dev.to/flaviolzsantos/historia-1-a-jornada-de-lory-e-a-indexacao-2led</guid>
      <description>&lt;p&gt;Nessa história, vamos abordar temas de indexação de um banco de dados&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Capítulo 1: O Início do Sistema de E-commerce&lt;/strong&gt;&lt;br&gt;
Lory, uma desenvolvedora entusiasta e cheia de ideias, começou a trabalhar em uma startup que tinha um e-commerce para atender pequenas lojas locais. Ela criou uma tabela simples com nome de &lt;em&gt;Order&lt;/em&gt; para armazenar os pedidos, contendo colunas como &lt;em&gt;OrderID&lt;/em&gt;, &lt;em&gt;CustomerID&lt;/em&gt;, &lt;em&gt;OrderDate&lt;/em&gt; e &lt;em&gt;Amount&lt;/em&gt;. O sistema era rápido, pois os primeiros clientes tinham poucos pedidos.&lt;/p&gt;

&lt;p&gt;No entanto, conforme o sucesso do sistema cresceu, mais lojas aderiram à plataforma e o volume de dados aumentou exponencialmente. Em poucos meses, a tabela Order acumulou milhões de registros. Lory percebeu o problema quando um lojista reclamou que ao tentar visualizar os pedidos de um cliente específico, a página levava minutos para carregar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O Desafio da Performance&lt;/strong&gt;&lt;br&gt;
Lory investigou o problema e percebeu que a consulta abaixo, usada para filtrar os pedidos por cliente, estava realizando um table scan, varrendo linha por linha da tabela:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SELECT * FROM Order WHERE CustomerID = 12345;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Essa query era ineficiente, especialmente com milhões de registros. Ela sabia que precisava resolver o problema rapidamente, ou os lojistas começariam a abandonar sua plataforma.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Solução com Indexação&lt;/strong&gt;&lt;br&gt;
Lory começou a estudar sobre técnicas de otimização de banco de dados e descobriu a indexação. Ela aprendeu que, ao criar um índice na coluna CustomerID, o banco de dados seria capaz de localizar os registros rapidamente, sem precisar examinar cada linha. Ela implementou o seguinte comando:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CREATE INDEX idx_customer_id ON Order(CustomerID);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;O impacto foi imediato. Consultas que antes levavam minutos passaram a ser concluídas em segundos. Lory ficou satisfeita ao ver os lojistas elogiando a rapidez do sistema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O Retorno do Desempenho Lento&lt;/strong&gt;&lt;br&gt;
Porém, nem tudo eram flores. Com o aumento do número de pedidos diários, Lory começou a notar uma lentidão nas operações de inserção de novos pedidos. Ela percebeu que, ao adicionar um novo pedido na tabela Order, o banco de dados também precisava atualizar o índice criado, o que estava consumindo tempo adicional.&lt;/p&gt;

&lt;p&gt;Ela testou a seguinte query de inserção e confirmou a lentidão:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;INSERT INTO Order (CustomerID, OrderDate, Amount) VALUES (12345, '2024-11-01', 150.00);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Lory entendeu que a indexação, embora eficiente para consultas, tinha um impacto negativo nas operações de escrita. Além disso, ela começou a notar que os índices criados estavam aumentando significativamente o espaço usado pelo banco de dados.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Capítulo 1.2: Lory e o Desafio das Inserções Lentas&lt;/strong&gt;&lt;br&gt;
Lory estava satisfeita com a solução de indexação que acelerou as consultas no sistema de e-commerce. As reclamações dos lojistas cessaram, e o sistema voltou a funcionar de forma eficiente. Porém, como todo bom desenvolvedor sabe, novos problemas sempre surgem quando um sistema cresce.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Chegada do Problema&lt;/strong&gt;&lt;br&gt;
Meses depois, Lory notou que as operações de inserção começaram a ficar lentas. O volume de vendas no sistema havia disparado, com dezenas de pedidos sendo registrados a cada segundo. Os lojistas, empolgados com o crescimento de seus negócios, começaram a relatar que novos pedidos levavam mais tempo que o previsto, aumentando a desistência dos consumidores no site.&lt;/p&gt;

&lt;p&gt;Lory investigou e percebeu que a lentidão estava diretamente relacionada aos índices que ela havia criado. A cada novo pedido inserido na tabela Order, o banco de dados precisava atualizar os índices associados, como o de &lt;em&gt;CustomerID&lt;/em&gt;. Isso estava causando um impacto significativo na performance das operações de escrita.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lory Buscou Algumas Soluções&lt;/strong&gt;&lt;br&gt;
Determinada a resolver o problema, Lory decidiu fazer uma pausa e pensar estrategicamente. Ela sabia que remover os índices não era uma opção, pois isso traria de volta o problema das consultas lentas. Então, ela começou a explorar alternativas para otimizar as inserções.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Solução: Inserts Assíncronos&lt;/strong&gt;&lt;br&gt;
Lory começou a planejar uma solução mais robusta. Ela adicionou filas para gerenciar as operações de inserção.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Implementação de Filas: Lory configurou uma fila de mensagens com RabbitMQ. Cada novo pedido era enviado para a fila e era processado por um serviço de inserção dedicado.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inserção Assíncrona: O serviço inseria os dados no banco de dados em segundo plano, mantendo os índices atualizados sem impactar diretamente a experiência dos lojistas.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Com isso, o sistema ficou preparado para lidar com picos de vendas sem sobrecarregar o banco de dados.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lory Aprende Sobre Particionamento&lt;/strong&gt;&lt;br&gt;
Mesmo com as otimizações, a tabela Order continuava crescendo. Lory começou a implementar o &lt;em&gt;particionamento de tabelas&lt;/em&gt; para dividir os dados em blocos menores por ano. Assim, os índices de cada partição eram menores e mais rápidos de atualizar. Ela particionou a tabela &lt;em&gt;Order&lt;/em&gt; com base no campo &lt;em&gt;OrderDate&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE Order_2024 (...);
CREATE TABLE Order_2025 (...);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;A Vitória&lt;/strong&gt;&lt;br&gt;
Graças às otimizações, o sistema de Lory continuou a crescer, suportando milhares de pedidos por minuto. Ela aprendeu que a indexação é essencial, mas o equilíbrio entre leitura e escrita é fundamental para o sucesso de um sistema em grande escala.&lt;/p&gt;

&lt;p&gt;Lory tornou-se uma desenvolvedora mais experiente, entendendo que resolver problemas de performance é como ajustar uma máquina em constante movimento. E assim, o e-commerce prosperou, com seus lojistas cada vez mais satisfeitos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lições Aprendidas&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Indexação é Fundamental, Mas Exige Planejamento&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A indexação acelera consultas ao organizar dados para buscas eficientes, mas pode impactar operações de escrita. É essencial balancear performance de leitura e escrita.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Monitoramento Contínuo é Essencial&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sistemas em crescimento apresentam novos desafios. Monitorar consultas e analisar o uso de índices regularmente ajuda a identificar gargalos antes que eles se tornem problemas críticos.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Assincronismo para Melhor Escalabilidade&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A implementação de filas com RabbitMQ e inserções assíncronas desacoplou a escrita da lógica principal do sistema, permitindo lidar com picos de vendas sem afetar a experiência do usuário.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Particionamento de Dados Aumenta a Eficiência&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dividir tabelas grandes em partições menores por ano, ajudou a manter os índices mais leves e rápidos, reduzindo o impacto tanto na leitura quanto na escrita.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;O Equilíbrio é a Chave&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nem sempre a solução para um problema será universal. Lory entendeu que a performance exige ajustes contínuos, considerando as demandas específicas de leitura e escrita.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Planejamento Previne Problemas Futuros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Estratégias como índices e o uso de filas prepararam o sistema de Lory para crescer sem comprometer a performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;7.&lt;strong&gt;Aprendizado e Adaptação Constantes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lory mostrou que ser uma boa desenvolvedora não é apenas implementar soluções, mas também revisar e aprimorar estratégias continuamente, acompanhando o crescimento do sistema.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essas lições são aplicáveis a qualquer sistema em crescimento e ilustram como desafios técnicos podem ser superados com planejamento estratégico e um mindset de aprendizado contínuo.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
