<?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: Marcus Dorbação</title>
    <description>The latest articles on DEV Community by Marcus Dorbação (@marcus-dorbacao).</description>
    <link>https://dev.to/marcus-dorbacao</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%2F1551826%2Ffe987f2f-c020-44dd-83d0-8db2388ab82a.jpg</url>
      <title>DEV Community: Marcus Dorbação</title>
      <link>https://dev.to/marcus-dorbacao</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/marcus-dorbacao"/>
    <language>en</language>
    <item>
      <title>SSE (Server-Sent Events): como funciona por baixo dos panos</title>
      <dc:creator>Marcus Dorbação</dc:creator>
      <pubDate>Thu, 16 Jul 2026 15:09:26 +0000</pubDate>
      <link>https://dev.to/marcus-dorbacao/sse-server-sent-events-como-funciona-por-baixo-dos-panos-422l</link>
      <guid>https://dev.to/marcus-dorbacao/sse-server-sent-events-como-funciona-por-baixo-dos-panos-422l</guid>
      <description>&lt;p&gt;Se você já precisou que um servidor "avisasse" o navegador quando algo mudasse — sem ficar dando refresh ou fazendo polling a cada X segundos — provavelmente esbarrou em duas opções: WebSocket ou &lt;strong&gt;SSE (Server-Sent Events)&lt;/strong&gt;. Este artigo foca no segundo: o que é, e como ele funciona tecnicamente.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é
&lt;/h2&gt;

&lt;p&gt;SSE é um mecanismo de comunicação &lt;strong&gt;unidirecional&lt;/strong&gt; (servidor → cliente), construído sobre HTTP comum. O servidor mantém uma única conexão aberta e vai empurrando eventos de texto para o cliente conforme eles acontecem, sem que o cliente precise ficar perguntando "tem novidade?".&lt;/p&gt;

&lt;p&gt;Diferente do WebSocket, não existe handshake especial nem troca de protocolo — é uma requisição HTTP GET normal, que simplesmente nunca termina.&lt;/p&gt;

&lt;h2&gt;
  
  
  O fluxo, passo a passo
&lt;/h2&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkc8mtxe2xw0u1n045cbm.jpg" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkc8mtxe2xw0u1n045cbm.jpg" alt=" " width="623" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. O cliente abre a conexão
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/stream&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api.exemplo.com&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;text/event-stream&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma requisição GET comum — nada de upgrade de protocolo.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. O servidor responde e não fecha a conexão
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;text/event-stream&lt;/span&gt;
&lt;span class="na"&gt;Cache-Control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;no-cache&lt;/span&gt;
&lt;span class="na"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keep-alive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;code&gt;Content-Type: text/event-stream&lt;/code&gt; avisa o cliente: "isso é um stream contínuo, não espere o corpo terminar".&lt;/p&gt;

&lt;h3&gt;
  
  
  3. O servidor envia eventos como texto
&lt;/h3&gt;

&lt;p&gt;Cada evento é um bloco separado por linha em branco:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;event: flag-update
data: {"flagKey": "novo-checkout", "value": true}

data: heartbeat

event: flag-update
data: {"flagKey": "cancelar-nota", "value": "variante-b"}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Campos possíveis:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Campo&lt;/th&gt;
&lt;th&gt;Para que serve&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;data:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;O payload do evento (pode ter várias linhas)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;event:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nome do tipo de evento — permite o cliente ter listeners diferentes por tipo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Identificador do evento, usado para retomar de onde parou após reconexão&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;retry:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Tempo em ms que o cliente deve esperar antes de tentar reconectar&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  4. O cliente processa cada evento
&lt;/h3&gt;

&lt;p&gt;No navegador, isso é nativo via &lt;code&gt;EventSource&lt;/code&gt;:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EventSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/stream&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flag-update&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="nx"&gt;e&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Atualização recebida:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&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;
  
  
  5. Se a conexão cair, reconecta sozinho
&lt;/h3&gt;

&lt;p&gt;Esse é um dos pontos mais úteis do SSE: o &lt;code&gt;EventSource&lt;/code&gt; reconecta automaticamente, sem precisar de código extra — e reenvia o header &lt;code&gt;Last-Event-ID&lt;/code&gt; com o último &lt;code&gt;id:&lt;/code&gt; recebido, permitindo o servidor retomar exatamente de onde parou, em vez de reenviar tudo desde o início.&lt;/p&gt;

&lt;h2&gt;
  
  
  Características técnicas que valem lembrar
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Só texto&lt;/strong&gt;: o payload é sempre string, geralmente JSON serializado — não dá para mandar binário direto&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unidirecional&lt;/strong&gt;: o cliente não consegue mandar dados de volta pela mesma conexão. Se precisar de um "ack" ou enviar algo, é uma requisição HTTP separada&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Roda sobre infraestrutura HTTP comum&lt;/strong&gt;: proxies, load balancers e CDNs já sabem lidar com isso, diferente do WebSocket, que às vezes exige suporte especial nesses componentes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limite de conexões no HTTP/1.1&lt;/strong&gt;: navegadores limitam a ~6 conexões simultâneas por domínio; isso deixa de ser um problema no HTTP/2, que multiplexa várias streams numa única conexão TCP&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quando faz sentido usar
&lt;/h2&gt;

&lt;p&gt;SSE é a escolha certa quando o fluxo de dados é &lt;strong&gt;só do servidor para o cliente&lt;/strong&gt; — notificações, atualizações de status, feeds em tempo real, mudanças de configuração. Se o cliente também precisa mandar dados pela mesma conexão em tempo real (ex: um chat, um jogo multiplayer), WebSocket é o caminho, porque ali a comunicação é bidirecional.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Feature Flags - Thinking</title>
      <dc:creator>Marcus Dorbação</dc:creator>
      <pubDate>Thu, 16 Jul 2026 14:51:59 +0000</pubDate>
      <link>https://dev.to/marcus-dorbacao/feature-flags-thinking-3o1f</link>
      <guid>https://dev.to/marcus-dorbacao/feature-flags-thinking-3o1f</guid>
      <description>&lt;h1&gt;
  
  
  Sistema de Feature Flags — Documentação Técnica
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Documentação em construção. Público-alvo: devs do time (uso técnico/API).&lt;br&gt;
Sistema avançado: rollout percentual, segmentação de usuários e A/B test.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Índice
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Visão geral&lt;/li&gt;
&lt;li&gt;Core de flags&lt;/li&gt;
&lt;li&gt;Targeting e segmentação&lt;/li&gt;
&lt;li&gt;Rollout progressivo&lt;/li&gt;
&lt;li&gt;A/B testing / Experimentação&lt;/li&gt;
&lt;li&gt;SDKs e integração técnica&lt;/li&gt;
&lt;li&gt;Autenticação (SDK Key)&lt;/li&gt;
&lt;li&gt;Sincronização em tempo real&lt;/li&gt;
&lt;li&gt;Eventos de conexão&lt;/li&gt;
&lt;li&gt;Webhooks (integração externa)&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Visão geral
&lt;/h2&gt;

&lt;p&gt;Sistema de feature flags construído do zero, com suporte a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flags booleanas e multivariáveis&lt;/li&gt;
&lt;li&gt;Segmentação por atributos de usuário&lt;/li&gt;
&lt;li&gt;Rollout percentual com bucketing consistente&lt;/li&gt;
&lt;li&gt;A/B testing com múltiplas variantes&lt;/li&gt;
&lt;li&gt;SDKs client-side e server-side&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Core de flags
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tipos de flag&lt;/strong&gt;: boolean (on/off) e multivariável (string/número/JSON), permitindo retornar variantes diferentes, não só ligar/desligar&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ambientes&lt;/strong&gt;: dev, staging, produção — cada um com seu próprio estado de flag&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kill switch&lt;/strong&gt;: desligar uma flag instantaneamente em produção, sem deploy&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Targeting e segmentação
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Regras de segmentação&lt;/strong&gt;: por atributo do usuário (país, plano, versão do app, device, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Targeting individual&lt;/strong&gt;: ligar a flag para usuários específicos (por ID, email)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grupos/coortes&lt;/strong&gt;: listas de usuários (ex: beta testers, funcionários internos)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Rollout progressivo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rollout percentual&lt;/strong&gt;: liberar gradualmente para uma fatia da base (5%, 10%, 50%...)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sticky bucketing&lt;/strong&gt;: garante que o mesmo usuário sempre caia na mesma variante entre sessões&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hash consistente&lt;/strong&gt;: normalmente hash do &lt;code&gt;user ID + flag key&lt;/code&gt; para decidir o bucket&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  A/B testing / Experimentação
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Múltiplas variantes com pesos configuráveis (ex: A 33%, B 33%, C 34%)&lt;/li&gt;
&lt;li&gt;Integração com analytics: disparar eventos de exposição (quem viu qual variante)&lt;/li&gt;
&lt;li&gt;Significância estatística geralmente delegada a uma ferramenta de análise externa, mas o sistema de flags precisa expor os dados de exposição&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  SDKs e integração técnica
&lt;/h2&gt;

&lt;h3&gt;
  
  
  SDK client-side vs server-side
&lt;/h3&gt;

&lt;p&gt;A diferença não é só "onde roda o código" — é uma questão de segurança e vazamento de informação.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server-side SDK&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Roda em ambiente confiável (backend)&lt;/li&gt;
&lt;li&gt;Pode ter acesso a todas as flags, incluindo as não lançadas, regras de segmentação completas e segredos usados no targeting&lt;/li&gt;
&lt;li&gt;Comunica-se direto com a API central ou via um &lt;strong&gt;Relay Proxy&lt;/strong&gt; (serviço intermediário que reduz chamadas repetidas)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Client-side SDK&lt;/strong&gt; (browser, mobile, apps)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Roda em ambiente não confiável — qualquer um pode inspecionar o payload&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nunca&lt;/strong&gt; deve receber a lista completa de flags. O backend avalia a flag para aquele usuário específico e envia só o payload já resolvido (ex: &lt;code&gt;flag X = true&lt;/code&gt;, &lt;code&gt;flag Y = variante B&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Isso é feito via endpoint do tipo &lt;code&gt;/sdk/eval?context={user}&lt;/code&gt;, retornando um payload minimalista&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regra crítica&lt;/strong&gt;: nunca usar a SDK key server-side (completa) dentro de um app client — isso vazaria todas as flags e regras internas&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Avaliação local vs remota
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Abordagem&lt;/th&gt;
&lt;th&gt;Latência&lt;/th&gt;
&lt;th&gt;Frescor dos dados&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Remota (thin client)&lt;/td&gt;
&lt;td&gt;Alta — chamada de rede a cada checagem&lt;/td&gt;
&lt;td&gt;Sempre atualizado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local (thick client, recomendada)&lt;/td&gt;
&lt;td&gt;Baixa — avaliação em memória&lt;/td&gt;
&lt;td&gt;Depende da estratégia de sync&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Estratégias de atualização do cache local:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Polling&lt;/strong&gt;: SDK pergunta "tem mudança?" a cada N segundos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streaming&lt;/strong&gt;: servidor empurra updates em tempo real assim que uma flag muda&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Muitos SDKs combinam os dois: streaming como canal principal + polling como fallback caso a conexão caia.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fallback / default values
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Todo flag check exige um valor &lt;strong&gt;default obrigatório&lt;/strong&gt; na chamada (nunca deixar o SDK "adivinhar")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hierarquia de fallback&lt;/strong&gt;:

&lt;ol&gt;
&lt;li&gt;Valor em cache local (último snapshot conhecido)&lt;/li&gt;
&lt;li&gt;Se nunca conectou → default fornecido no código de chamada&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Falha do serviço de flags nunca deve travar a aplicação — deve ser silenciosa e logada&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timeout de inicialização&lt;/strong&gt;: tempo máximo de espera no boot para o primeiro fetch (ex: 5s); depois disso, segue com defaults e atualiza quando possível&lt;/li&gt;
&lt;li&gt;Emitir métrica/log quando o SDK cai em modo fallback, para sinalizar degradação do serviço&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Autenticação (SDK Key)
&lt;/h2&gt;

&lt;p&gt;A SDK key funciona como um &lt;strong&gt;bearer token&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Authorization: Bearer sdk-a1b2c3d4...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Elemento&lt;/th&gt;
&lt;th&gt;Papel&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SDK key (bearer token)&lt;/td&gt;
&lt;td&gt;Autentica + resolve escopo (projeto/ambiente) — não participa da decisão de segmentação&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context (key, plan, country...)&lt;/td&gt;
&lt;td&gt;Fornece os dados para a decisão de segmentação e rollout&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Exemplo de request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;/evaluate&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Headers:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer sdk-a1b2c3d4..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;Body:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"flagKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cancelar-nota-fiscal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user-12345"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"plan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"enterprise"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BR"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Por que não expor projectId/environment como parâmetros públicos
&lt;/h3&gt;

&lt;p&gt;Alternativa descartada: passar &lt;code&gt;?project=app-mobile&amp;amp;env=production&lt;/code&gt; abertamente, sem token.&lt;/p&gt;

&lt;p&gt;Problemas dessa abordagem:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Enumeração&lt;/strong&gt; — projectId previsível permite testar/descobrir outros projetos/ambientes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sem autenticação&lt;/strong&gt; — impossível distinguir chamada legítima de bisbilhotagem&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vazamento de lógica de negócio&lt;/strong&gt; — testar contexts publicamente permite reconstruir regras de segmentação por engenharia reversa&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sem revogação/rotação&lt;/strong&gt; — sem token não há "chave" para cortar acesso; seria preciso mudar a própria estrutura da API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sem rate limiting/billing por cliente&lt;/strong&gt; — impossível medir uso ou isolar consumidores&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DoS mais fácil&lt;/strong&gt; — sem identificação, não dá para aplicar throttling seletivo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mistura acidental de ambientes&lt;/strong&gt; — sem credencial vinculante, é mais fácil um client de produção acessar staging por engano&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Sincronização em tempo real
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Por que webhook não serve como mecanismo de sync do SDK
&lt;/h3&gt;

&lt;p&gt;Webhook exige que o &lt;strong&gt;servidor inicie uma conexão de saída até o cliente&lt;/strong&gt; — o que não funciona para a maioria dos consumidores reais de SDK:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontend/browser: sem endereço público&lt;/li&gt;
&lt;li&gt;App mobile: sem IP público, sem porta aberta&lt;/li&gt;
&lt;li&gt;Backend atrás de NAT/firewall corporativo: porta não exposta&lt;/li&gt;
&lt;li&gt;Serverless/Lambda: função só existe durante a execução&lt;/li&gt;
&lt;li&gt;Múltiplas réplicas atrás de load balancer: ambíguo para qual réplica enviar&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por isso, o padrão adotado (como na maioria dos sistemas de feature flag do mercado) é o &lt;strong&gt;inverso&lt;/strong&gt;: o cliente inicia a conexão de saída (streaming ou polling) e mantém ela aberta.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSE como alternativa ao WebSocket
&lt;/h3&gt;

&lt;p&gt;WebSocket é bidirecional e mais pesado que o necessário — o caso de uso aqui é apenas &lt;strong&gt;server → client&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SSE (Server-Sent Events)&lt;/strong&gt; cobre esse caso:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conexão HTTP simples, unidirecional&lt;/li&gt;
&lt;li&gt;Reconexão automática nativa&lt;/li&gt;
&lt;li&gt;Funciona sobre HTTP/1.1 comum, sem upgrade de protocolo&lt;/li&gt;
&lt;li&gt;Mais simples de implementar mantendo tempo real&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fc2VxdWVuY2VEaWFncmFtCiAgICBwYXJ0aWNpcGFudCBDIGFzIFNESyBDbGllbnQKICAgIHBhcnRpY2lwYW50IEEgYXMgQVBJIChBdXRoKQogICAgcGFydGljaXBhbnQgUyBhcyBTeW5jIFNlcnZpY2UgKFNTRSkKCiAgICBDLT4-QTogUE9TVCAvYXV0aCAob3JnLCBhcHAsIGFtYmllbnRlKQogICAgQS0tPj5DOiBTREsgS2V5IChiZWFyZXIgdG9rZW4pCiAgICBDLT4-UzogR0VUIC9zdHJlYW0gKEF1dGhvcml6YXRpb246IEJlYXJlciAuLi4pCiAgICBTLS0-PkM6IHNuYXBzaG90IGluaWNpYWwgZGUgZmxhZ3MKICAgIE5vdGUgb3ZlciBTOiBmbGFnIGFsdGVyYWRhIG5vIHBhaW5lbAogICAgUy0tPj5DOiBldmVudG8gU1NFICh1cGRhdGUgZGUgZmxhZykKICAgIEMtPj5DOiBhdHVhbGl6YSBjYWNoZSBsb2NhbAo%3D" alt="fluxo de autenticação SSE" width="735" height="522"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Eventos de conexão
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;SdkConnected&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Dispara quando o SDK abre a conexão de streaming (SSE/WebSocket) &lt;strong&gt;e&lt;/strong&gt; o token é validado com sucesso. Não é só "TCP conectou" — é "conexão autenticada e pronta para receber updates daquele escopo (org/app/ambiente)".&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;SdkDisconnected&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Dispara quando a conexão cai, por um de três motivos (importante diferenciar no payload):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fechamento gracioso&lt;/strong&gt; — shutdown, deploy, scale-down&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timeout/heartbeat perdido&lt;/strong&gt; — SDK parou de responder ao keep-alive&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Erro de rede&lt;/strong&gt; — queda abrupta&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Diferenciar o motivo importa para observabilidade: uma queda maciça de conexões pode ser "todo mundo fez deploy ao mesmo tempo" (normal) ou "o serviço de streaming caiu" (crítico).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pontos de atenção:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reconexões automáticas com backoff podem gerar ruído (&lt;code&gt;SdkDisconnected → SdkConnected&lt;/code&gt; repetidos) — considerar debounce/agregação nas métricas&lt;/li&gt;
&lt;li&gt;Incluir um &lt;code&gt;connectionId&lt;/code&gt; único por sessão de streaming para correlacionar conexão/desconexão e calcular duração&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Usos práticos:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Observabilidade — quantos SDKs ativos por ambiente&lt;/li&gt;
&lt;li&gt;Detecção de degradação — queda anormal indica problema no Sync service&lt;/li&gt;
&lt;li&gt;Billing/capacity planning — se cobrança for por conexões simultâneas&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Webhooks (integração externa)
&lt;/h2&gt;

&lt;p&gt;Webhook &lt;strong&gt;não é&lt;/strong&gt; o mecanismo de sincronização do SDK, mas é útil como &lt;strong&gt;feature de integração opcional&lt;/strong&gt;, quando o receptor é um serviço backend do próprio cliente, controlado por eles, com endpoint público de propósito.&lt;/p&gt;

&lt;p&gt;Exemplos de uso:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Notificar o sistema de CI/CD do cliente quando uma flag mudar em produção&lt;/li&gt;
&lt;li&gt;Sincronizar com um sistema de config interno do cliente&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modelo proposto: URL de webhook registrada no momento da autenticação (junto com organização/aplicação/ambiente), salva em uma tabela de webhooks associada à chave/token.&lt;/p&gt;




&lt;h2&gt;
  
  
  Em aberto
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Detalhar payload dos eventos &lt;code&gt;SdkConnected&lt;/code&gt;/&lt;code&gt;SdkDisconnected&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;[ ] Fluxo completo de &lt;code&gt;evaluate()&lt;/code&gt; (resolução de token → busca da flag → segmentação → rollout → resultado)&lt;/li&gt;
&lt;li&gt;[ ] Desenho do schema de dados completo&lt;/li&gt;
&lt;li&gt;[ ] Desenho detalhado da tabela de webhooks como feature de integração&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>devops</category>
      <category>systemdesign</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
