<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 "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.</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('sns', region_name='us-east-1')
def publicar_pedido_criado(pedido_id, cliente_email, valor):
"""Publica evento de pedido criado no SNS"""
mensagem = {
'pedido_id': pedido_id,
'cliente_email': cliente_email,
'valor': valor,
'timestamp': '2024-01-15T10:30:00Z'
}
response = sns_client.publish(
TopicArn='arn:aws:sns:us-east-1:123456789012:pedidos-criados',
Subject='Novo Pedido Criado',
Message=json.dumps(mensagem),
MessageStructure='json'
)
return response['MessageId']
Uso
publicar_pedido_criado(
pedido_id='PED123',
cliente_email='cliente@example.com',
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('sns', region_name='us-east-1')
sqs_client = boto3.client('sqs', region_name='us-east-1')
Publicando com atributos
def publicar_com_atributos(pedido_valor, tipo_pedido):
"""Publica com atributos para filtro"""
sns_client.publish(
TopicArn='arn:aws:sns:us-east-1:123456789012:pedidos',
Message='Novo pedido processado',
MessageAttributes={
'tipo': {
'StringValue': tipo_pedido, # 'premium' ou 'normal'
'DataType': 'String'
},
'valor': {
'StringValue': str(pedido_valor),
'DataType': 'Number'
}
}
)
Subscribe com filtro policy
def subscrever_com_filtro(fila_url, topico_arn):
"""Cria subscription com filtro para pedidos premium acima de R$500"""
filter_policy = {
'tipo': ['premium'],
'valor': [{'numeric': ['>=', 500]}]
}
response = sns_client.subscribe(
TopicArn=topico_arn,
Protocol='sqs',
Endpoint=fila_url,
Attributes={
'FilterPolicy': json.dumps(filter_policy)
}
)
return response['SubscriptionArn']
publicar_com_atributos(750.00, 'premium')
publicar_com_atributos(150.00, 'normal')
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('sns')
sqs = boto3.client('sqs')
lambda_client = boto3.client('lambda')
1. Publisher: Publicar evento no SNS
def publicar_evento_pedido(pedido_id, cliente_id):
"""Publica evento no tópico SNS"""
mensagem = {
'pedido_id': pedido_id,
'cliente_id': cliente_id,
'timestamp': datetime.now().isoformat()
}
sns.publish(
TopicArn='arn:aws:sns:us-east-1:123456789012:eventos-pedidos',
Message=json.dumps(mensagem),
MessageAttributes={
'evento_tipo': {
'StringValue': 'pedido.criado',
'DataType': 'String'
}
}
)
2. Lambda Handler: Consumir de SQS
def lambda_handler(event, context):
"""Lambda acionada por mensagens SQS (originalmente do SNS)"""
for record in event['Records']:
SQS envolve a mensagem original em um JSON
body = json.loads(record['body'])
message = json.loads(body['Message'])
pedido_id = message['pedido_id']
cliente_id = message['cliente_id']
Processar pedido
print(f"Processando pedido {pedido_id} do cliente {cliente_id}")
Lógica de negócio aqui
enviar_confirmacao_email(cliente_id)
atualizar_inventario(pedido_id)
return {
'statusCode': 200,
'body': json.dumps('Pedidos processados')
}
def enviar_confirmacao_email(cliente_id):
"""Simula envio de email"""
print(f"Email enviado para cliente {cliente_id}")
def atualizar_inventario(pedido_id):
"""Simula atualização de inventário"""
print(f"Inventário atualizado para pedido {pedido_id}")
3. Setup (executar uma única vez)
def configurar_arquitetura():
"""Configura SNS → SQS → Lambda"""
Criar fila SQS
fila = sqs.create_queue(
QueueName='pedidos-processamento',
Attributes={
'VisibilityTimeout': '300',
'MessageRetentionPeriod': '86400'
}
)
fila_url = fila['QueueUrl']
Inscrever fila no tópico SNS
sns.subscribe(
TopicArn='arn:aws:sns:us-east-1:123456789012:eventos-pedidos',
Protocol='sqs',
Endpoint=fila_url
)
print(f"Arquitetura configurada. Fila: {fila_url}")</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>