Cloud & Infraestrutura

O que Todo Dev Deve Saber sobre SNS: Fan-out Pattern, Filtros e Integração com SQS e Lambda

8 min de leitura

O que Todo Dev Deve Saber sobre SNS: Fan-out Pattern, Filtros e Integração com SQS e Lambda

O que é SNS e Por Que Importa Amazon Simple Notification Service (SNS) é um serviço de mensageria pub/sub totalmente gerenciado que desacopla componentes de sua arquitetura. Diferente de filas (como SQS), SNS trabalha com o modelo "publicador-assinante", onde uma mensagem é entregue a múltiplos receptores simultaneamente. É o padrão ideal quando você precisa que um evento dispare ações em vários sistemas independentes. A importância do SNS está justamente nesse desacoplamento: seu serviço de pedidos não precisa conhecer o serviço de notificações, o de relatórios ou o de envio de emails. Todos se inscrevem no mesmo tópico SNS e recebem a mensagem quando precisam. Isso torna sistemas mais escaláveis, resilientes e fáceis de manter. Fan-out Pattern: Distribuindo Mensagens em Escala Conceito Fundamental Fan-out é o padrão arquitetural onde uma única mensagem publicada em um tópico SNS é distribuída para múltiplos destinos (subscribers) simultaneamente. É como um broadcast: você fala uma vez e todos ouvem. Isso contrasta com arquiteturas acopladas onde

<h2>O que é SNS e Por Que Importa</h2>

<p>Amazon Simple Notification Service (SNS) é um serviço de mensageria pub/sub totalmente gerenciado que desacopla componentes de sua arquitetura. Diferente de filas (como SQS), SNS trabalha com o modelo &quot;publicador-assinante&quot;, onde uma mensagem é entregue a múltiplos receptores simultaneamente. É o padrão ideal quando você precisa que um evento dispare ações em vários sistemas independentes.</p>

<p>A importância do SNS está justamente nesse desacoplamento: seu serviço de pedidos não precisa conhecer o serviço de notificações, o de relatórios ou o de envio de emails. Todos se inscrevem no mesmo tópico SNS e recebem a mensagem quando precisam. Isso torna sistemas mais escaláveis, resilientes e fáceis de manter.</p>

<h2>Fan-out Pattern: Distribuindo Mensagens em Escala</h2>

<h3>Conceito Fundamental</h3>

<p>Fan-out é o padrão arquitetural onde uma única mensagem publicada em um tópico SNS é distribuída para múltiplos destinos (subscribers) simultaneamente. É como um broadcast: você fala uma vez e todos ouvem. Isso contrasta com arquiteturas acopladas onde o publicador precisa chamar cada consumidor manualmente.</p>

<h3>Implementação Prática</h3>

<p>Imagine um e-commerce onde um pedido é criado. Você publica um evento <code>PedidoCriado</code> no SNS e diferentes sistemas se inscrevem: sistema de pagamento, sistema de inventário, serviço de notificação ao cliente e sistema de analytics.</p>

<pre><code class="language-python">import boto3

import json

sns_client = boto3.client(&#039;sns&#039;, region_name=&#039;us-east-1&#039;)

def publicar_pedido_criado(pedido_id, cliente_email, valor):

&quot;&quot;&quot;Publica evento de pedido criado no SNS&quot;&quot;&quot;

mensagem = {

&#039;pedido_id&#039;: pedido_id,

&#039;cliente_email&#039;: cliente_email,

&#039;valor&#039;: valor,

&#039;timestamp&#039;: &#039;2024-01-15T10:30:00Z&#039;

}

response = sns_client.publish(

TopicArn=&#039;arn:aws:sns:us-east-1:123456789012:pedidos-criados&#039;,

Subject=&#039;Novo Pedido Criado&#039;,

Message=json.dumps(mensagem),

MessageStructure=&#039;json&#039;

)

return response[&#039;MessageId&#039;]

Uso

publicar_pedido_criado(

pedido_id=&#039;PED123&#039;,

cliente_email=&#039;cliente@example.com&#039;,

valor=299.90

)</code></pre>

<p>Cada subscriber (SQS, Lambda, email, webhook) recebe essa mensagem independentemente, permitindo processamento paralelo e desacoplado.</p>

<h2>Filtros SNS: Processamento Inteligente de Mensagens</h2>

<h3>Por Que Filtros Existem</h3>

<p>Sem filtros, toda mensagem publicada no tópico vai para todos os subscribers. Isso gera desperdício: o sistema de pagamento recebe eventos de inventário, e vice-versa. Filtros SNS permitem que cada subscriber receba apenas mensagens relevantes baseadas em atributos.</p>

<h3>Implementando Filtros</h3>

<p>Filtros funcionam através de atributos de mensagem. Ao publicar, você adiciona metadados; ao subscrever, você define condições. Veja:</p>

<pre><code class="language-python">import boto3

import json

sns_client = boto3.client(&#039;sns&#039;, region_name=&#039;us-east-1&#039;)

sqs_client = boto3.client(&#039;sqs&#039;, region_name=&#039;us-east-1&#039;)

Publicando com atributos

def publicar_com_atributos(pedido_valor, tipo_pedido):

&quot;&quot;&quot;Publica com atributos para filtro&quot;&quot;&quot;

sns_client.publish(

TopicArn=&#039;arn:aws:sns:us-east-1:123456789012:pedidos&#039;,

Message=&#039;Novo pedido processado&#039;,

MessageAttributes={

&#039;tipo&#039;: {

&#039;StringValue&#039;: tipo_pedido, # &#039;premium&#039; ou &#039;normal&#039;

&#039;DataType&#039;: &#039;String&#039;

},

&#039;valor&#039;: {

&#039;StringValue&#039;: str(pedido_valor),

&#039;DataType&#039;: &#039;Number&#039;

}

}

)

Subscribe com filtro policy

def subscrever_com_filtro(fila_url, topico_arn):

&quot;&quot;&quot;Cria subscription com filtro para pedidos premium acima de R$500&quot;&quot;&quot;

filter_policy = {

&#039;tipo&#039;: [&#039;premium&#039;],

&#039;valor&#039;: [{&#039;numeric&#039;: [&#039;&gt;=&#039;, 500]}]

}

response = sns_client.subscribe(

TopicArn=topico_arn,

Protocol=&#039;sqs&#039;,

Endpoint=fila_url,

Attributes={

&#039;FilterPolicy&#039;: json.dumps(filter_policy)

}

)

return response[&#039;SubscriptionArn&#039;]

publicar_com_atributos(750.00, &#039;premium&#039;)

publicar_com_atributos(150.00, &#039;normal&#039;)

A fila recebe apenas o primeiro</code></pre>

<p>Apenas mensagens que correspondem aos critérios são entregues, economizando processamento e custos.</p>

<h2>Integração SNS + SQS + Lambda</h2>

<h3>Arquitetura Completa</h3>

<p>A combinação SNS → SQS → Lambda é poderosa: SNS garante que múltiplos sistemas saibam do evento, SQS oferece fila durável (retry automático, dead-letter queue), e Lambda processa em paralelo sem gerenciar servidores. SNS publica, SQS armazena temporariamente, Lambda consome.</p>

<h3>Código Funcional Completo</h3>

<pre><code class="language-python">import boto3

import json

from datetime import datetime

sns = boto3.client(&#039;sns&#039;)

sqs = boto3.client(&#039;sqs&#039;)

lambda_client = boto3.client(&#039;lambda&#039;)

1. Publisher: Publicar evento no SNS

def publicar_evento_pedido(pedido_id, cliente_id):

&quot;&quot;&quot;Publica evento no tópico SNS&quot;&quot;&quot;

mensagem = {

&#039;pedido_id&#039;: pedido_id,

&#039;cliente_id&#039;: cliente_id,

&#039;timestamp&#039;: datetime.now().isoformat()

}

sns.publish(

TopicArn=&#039;arn:aws:sns:us-east-1:123456789012:eventos-pedidos&#039;,

Message=json.dumps(mensagem),

MessageAttributes={

&#039;evento_tipo&#039;: {

&#039;StringValue&#039;: &#039;pedido.criado&#039;,

&#039;DataType&#039;: &#039;String&#039;

}

}

)

2. Lambda Handler: Consumir de SQS

def lambda_handler(event, context):

&quot;&quot;&quot;Lambda acionada por mensagens SQS (originalmente do SNS)&quot;&quot;&quot;

for record in event[&#039;Records&#039;]:

SQS envolve a mensagem original em um JSON

body = json.loads(record[&#039;body&#039;])

message = json.loads(body[&#039;Message&#039;])

pedido_id = message[&#039;pedido_id&#039;]

cliente_id = message[&#039;cliente_id&#039;]

Processar pedido

print(f&quot;Processando pedido {pedido_id} do cliente {cliente_id}&quot;)

Lógica de negócio aqui

enviar_confirmacao_email(cliente_id)

atualizar_inventario(pedido_id)

return {

&#039;statusCode&#039;: 200,

&#039;body&#039;: json.dumps(&#039;Pedidos processados&#039;)

}

def enviar_confirmacao_email(cliente_id):

&quot;&quot;&quot;Simula envio de email&quot;&quot;&quot;

print(f&quot;Email enviado para cliente {cliente_id}&quot;)

def atualizar_inventario(pedido_id):

&quot;&quot;&quot;Simula atualização de inventário&quot;&quot;&quot;

print(f&quot;Inventário atualizado para pedido {pedido_id}&quot;)

3. Setup (executar uma única vez)

def configurar_arquitetura():

&quot;&quot;&quot;Configura SNS → SQS → Lambda&quot;&quot;&quot;

Criar fila SQS

fila = sqs.create_queue(

QueueName=&#039;pedidos-processamento&#039;,

Attributes={

&#039;VisibilityTimeout&#039;: &#039;300&#039;,

&#039;MessageRetentionPeriod&#039;: &#039;86400&#039;

}

)

fila_url = fila[&#039;QueueUrl&#039;]

Inscrever fila no tópico SNS

sns.subscribe(

TopicArn=&#039;arn:aws:sns:us-east-1:123456789012:eventos-pedidos&#039;,

Protocol=&#039;sqs&#039;,

Endpoint=fila_url

)

print(f&quot;Arquitetura configurada. Fila: {fila_url}&quot;)</code></pre>

<p>O fluxo é: <code>publicar_evento_pedido()</code> → SNS publica → SQS recebe → Lambda processa. Se Lambda falhar, a mensagem volta à fila automaticamente (retry).</p>

<h2>Conclusão</h2>

<p>Três pilares para dominar SNS: primeiro, entenda que SNS é <strong>publicador-assinante para eventos distribuídos</strong>, não filas. Segundo, use <strong>filtros SNS para rotear mensagens inteligentemente</strong> e economizar processamento. Terceiro, combine <strong>SNS + SQS + Lambda</strong> para arquiteturas robustas, desacopladas e escaláveis que processam eventos em paralelo sem deixar nenhum cair.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://docs.aws.amazon.com/sns/" target="_blank" rel="noopener noreferrer">AWS SNS Documentation</a></li>

<li><a href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sns-sqs-as-subscriptions.html" target="_blank" rel="noopener noreferrer">AWS SQS with SNS Fan-out Pattern</a></li>

<li><a href="https://docs.aws.amazon.com/sns/latest/dg/sns-message-filtering.html" target="_blank" rel="noopener noreferrer">SNS Message Filtering</a></li>

<li><a href="https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html" target="_blank" rel="noopener noreferrer">Lambda with SQS Event Source</a></li>

<li><a href="https://docs.aws.amazon.com/wellarchitected/latest/userguide/messaging.html" target="_blank" rel="noopener noreferrer">AWS Well-Architected Framework - Messaging</a></li>

</ul>

Comentários

Mais em Cloud & Infraestrutura

Well-Architected Framework: Os Seis Pilares na Prática na Prática
Well-Architected Framework: Os Seis Pilares na Prática na Prática

Well-Architected Framework: Os Seis Pilares na Prática O AWS Well-Architected...

O que Todo Dev Deve Saber sobre EventBridge: Event Bus, Rules, Pipes e SaaS Integrations
O que Todo Dev Deve Saber sobre EventBridge: Event Bus, Rules, Pipes e SaaS Integrations

Event Bus: Fundação do EventBridge O Event Bus é o componente central do AWS...

Como Usar API Gateway: REST API, HTTP API e WebSocket API na Prática em Produção
Como Usar API Gateway: REST API, HTTP API e WebSocket API na Prática em Produção

Entendendo as Três Arquiteturas do API Gateway O AWS API Gateway oferece três...