AWS Learning
Messaging & Streaming

Amazon SNS (Simple Notification Service)

Simple Notification Service, Pub/Sub, Fan-out, Message Filtering

Tổng quan

Amazon SNS là fully managed pub/sub messaging service để gửi notifications đến nhiều subscribers cùng lúc.

┌───────────────────────────────────────────────────────────────────┐
│                    SNS PUB/SUB MODEL                              │
├───────────────────────────────────────────────────────────────────┤
│                                                                   │
│   Publisher (1)                                                   │
│         │                                                         │
│       ↓                                                           │
│   ┌───────────────────────────────────────┐                       │
│   │           SNS TOPIC                   │                       │
│   │    "order-created-topic"              │                       │
│   └───────────────────────────────────────┘                       │
│       │           │           │             │                     │
│       ↓           ↓           ↓           ↓                       │
│   ┌───────┐   ┌───────┐   ┌───────┐   ┌───────┐                   │
│   │  SQS  │   │Lambda │   │ Email │   │ HTTP  │                   │
│   │ Queue │   │       │   │       │   │Endpoint │                 │
│   └───────┘   └───────┘   └───────┘   └───────┘                   │
│                                                                   │
│   Subscribers (many) - TẤT CẢ đều nhận message                    │
│                                                                   │
└───────────────────────────────────────────────────────────────────┘

SNS vs SQS

SNSSQS
ModelPub/Sub (push)Queue (pull)
Message Delivery1 message → ALL subscribers1 message → 1 consumer
PersistenceNo (instant delivery)Yes (up to 14 days)
ConsumerPassive (receive push)Active (poll messages)

1. Core Concepts

1.1 Topic

┌─────────────────────────────────────────────────────────────────┐
│                       SNS TOPIC                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   Topic = "Channel" để publishers gửi messages                  │
│                                                                 │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │  Topic ARN: arn:aws:sns:us-east-1:123456789:my-topic    │   │
│   │                                                         │   │
│   │  Limits:                                                │   │
│   │  • Up to 12,500,000 subscriptions per topic             │   │
│   │  • Up to 100,000 topics per account                     │   │
│   └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

1.2 Message Structure

┌─────────────────────────────────────────────────────────────────┐
│                    SNS MESSAGE                                  │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │  {                                                      │   │
│   │    "Type": "Notification",                              │   │
│   │    "MessageId": "uuid",                                 │   │
│   │    "TopicArn": "arn:aws:sns:...",                       │   │
│   │    "Subject": "Optional subject",                       │   │
│   │    "Message": "Your actual message content",            │   │
│   │    "Timestamp": "2024-01-01T00:00:00.000Z",             │   │
│   │    "MessageAttributes": {                               │   │
│   │      "OrderType": {"Type": "String", "Value": "online"} │   │
│   │    }                                                    │   │
│   │  }                                                      │   │
│   └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│   Max message size: 256 KB                                      │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

1.3 Publishers

PublisherMô tả
AWS SDKPublish API từ applications
CloudWatch AlarmsAlert notifications
S3 EventsBucket notifications
LambdaFunction triggers
Many AWS ServicesEventBridge, CodePipeline...

2. Subscription Types

2.1 Tất cả Subscription Protocols

┌─────────────────────────────────────────────────────────────────┐
│                  SUBSCRIPTION PROTOCOLS                         │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   APPLICATION INTEGRATION:                                      │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │  • SQS Queue     → Fan-out to queues                    │   │
│   │  • Lambda        → Serverless processing                │   │
│   │  • Kinesis       → Data Firehose (via Firehose)         │   │
│   │  • HTTP/HTTPS    → Custom webhooks                      │   │
│   └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│   DIRECT NOTIFICATIONS:                                         │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │  • Email/Email-JSON  → User notifications               │   │
│   │  • SMS               → Mobile text messages             │   │
│   │  • Mobile Push       → iOS, Android, Fire OS            │   │
│   └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

2.2 Protocol Details

ProtocolUse CaseConfirmation
SQSDecouple processingAuto-confirmed
LambdaServerless processingAuto-confirmed
HTTP/HTTPSWebhooks, APIsMust confirm subscription
EmailUser alertsMust confirm via link
SMSMobile alertsNo confirmation needed
Mobile PushApp notificationsDevice registration

2.3 Subscription Confirmation

┌──────────────────────────────────────────────────────────────────┐
│              SUBSCRIPTION CONFIRMATION                           │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│   HTTP/HTTPS & Email subscriptions require confirmation:         │
│                                                                  │
│   1. Create subscription → Status: "Pending confirmation"        │
│                                 ↓                                │
│   2. SNS sends confirmation message                              │
│      • HTTP: POST with SubscribeURL                              │
│      • Email: Click confirmation link                            │
│                                 ↓                                │
│   3. Subscriber confirms                                         │
│                                 ↓                                │
│   4. Status: "Confirmed" → Ready to receive messages             │
│                                                                  │
│   ⚠️  Unconfirmed subscriptions auto-delete after 3 days         │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

3. Message Filtering

3.1 Filter Policy

┌─────────────────────────────────────────────────────────────────┐
│                   MESSAGE FILTERING                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   Without Filter: ALL subscribers receive ALL messages          │
│                                                                 │
│   With Filter Policy (JSON):                                    │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │  Publisher sends:                                       │   │
│   │  Message: "Order placed"                                │   │
│   │  MessageAttributes: {                                   │   │
│   │    "eventType": "order",                                │   │
│   │    "store": "online",                                   │   │
│   │    "price": 150                                         │   │
│   │  }                                                      │   │
│   └─────────────────────────────────────────────────────────┘   │
│                        ↓                                        │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │  Subscriber 1 (Online Orders Only):                     │   │
│   │  FilterPolicy: {"store": ["online"]}                    │   │
│   │  → ✅ RECEIVES                                          │   │
│   ├─────────────────────────────────────────────────────────┤   │
│   │  Subscriber 2 (In-Store Orders Only):                   │   │
│   │  FilterPolicy: {"store": ["in-store"]}                  │   │
│   │  → ❌ FILTERED OUT                                      │   │
│   ├─────────────────────────────────────────────────────────┤   │
│   │  Subscriber 3 (High Value Orders):                      │   │
│   │  FilterPolicy: {"price": [{"numeric": [">=", 100]}]}    │   │
│   │  → ✅ RECEIVES (150 >= 100)                             │   │
│   └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

3.2 Filter Policy Operators

OperatorExampleMatches
Exact match{"color": ["red"]}color = "red"
OR{"color": ["red", "blue"]}color = "red" OR "blue"
Prefix{"region": [{"prefix": "us-"}]}region starts with "us-"
Numeric{"price": [{"numeric": [">", 100]}]}price > 100
Exists{"color": [{"exists": true}]}color attribute exists
Anything-but{"color": [{"anything-but": "red"}]}color != "red"

3.3 Filter Policy Scope

┌─────────────────────────────────────────────────────────────────┐
│              FILTER POLICY SCOPE                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   MessageAttributes (default):                                  │
│   • Filter based on message metadata                            │
│   • FilterPolicyScope: "MessageAttributes"                      │
│                                                                 │
│   MessageBody:                                                  │
│   • Filter based on message content (JSON)                      │
│   • FilterPolicyScope: "MessageBody"                            │
│   • Message body must be valid JSON                             │
│                                                                 │
│   Example (MessageBody filter):                                 │
│   Message: {"customer": {"type": "premium"}, "amount": 500}     │
│   FilterPolicy: {"customer": {"type": ["premium"]}}             │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

4. SNS + SQS Fan-out

4.1 Vấn đề và Giải pháp

Vấn đề: Một event cần trigger nhiều xử lý độc lập

Ví dụ: User upload ảnh → cần làm:
  1. Tạo thumbnail
  2. Phân tích AI
  3. Archive lên Glacier
  4. Gửi email thông báo

❌ KHÔNG TỐT: 1 Lambda xử lý TẤT CẢ
   → Nếu step 3 fail → ảnh hưởng cả hệ thống
   → Không scale được từng phần riêng

Giải pháp: Fan-out = "Phân nhánh" message ra nhiều hướng

                      S3 (upload ảnh)


                    ┌─────────────┐
                    │  SNS Topic  │  ← Nhận 1 event
                    └─────────────┘

        ┌──────────┬───────┴───────┬──────────┐
        ↓          ↓               ↓          ↓
    ┌──────┐   ┌──────┐       ┌──────┐   ┌──────┐
    │SQS 1 │   │SQS 2 │       │SQS 3 │   │Lambda│
    └──────┘   └──────┘       └──────┘   └──────┘
        ↓          ↓               ↓          ↓
    Thumbnail   AI phân tích   Archive    Email

4.2 Tại sao dùng SQS thay vì Lambda trực tiếp?

SNS → LambdaSNS → SQS → Consumer
Buffering❌ Lambda phải sẵn sàng✅ SQS giữ message khi app down
RetryLambda tự handle✅ SQS có built-in retry
DLQPhức tạp hơn✅ DLQ dễ config
Rate limiting❌ Lambda bị overwhelm✅ Consumer xử lý theo tốc độ

4.3 Fan-out với Message Filtering

⚠️ QUAN TRỌNG: Filter xảy ra ở tầng SNS, TRƯỚC KHI gửi đến SQS

┌─────────────────────────────────────────────────────────────────────────────┐
│                    MESSAGE FILTERING FLOW                                   │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   Publisher gửi: { "orderType": "online" }                                  │
│                         │                                                   │
│                          ↓                                                  │
│                   ┌─────────────┐                                           │
│                   │  SNS Topic  │                                           │
│                   └──────┬──────┘                                           │
│                         │                                                   │
│        ┌─────────────────┼─────────────────┐                                │
│        ↓                 ↓                 ↓                                │
│   ┌──────────┐     ┌──────────┐     ┌──────────┐                            │
│   │Filter:   │     │Filter:   │     │Filter:   │  ← Filter Policy gắn       │
│   │"online"  │     │"in-store"│     │ (none)   │    VÀO SUBSCRIPTION        │
│   └────┬─────┘     └────┬─────┘     └────┬─────┘                            │
│        │                │               │                                   │
│    ✅ MATCH         ❌ SKIP          ✅ MATCH                               │
│        │                ✖               │                                   │
│        ↓                                 ↓                                  │
│   ┌──────────┐                     ┌──────────┐                             │
│   │SQS Online│                     │SQS All   │                             │
│   └──────────┘                     └──────────┘                             │
│                                                                             │
│   ⚡ SNS filter TRƯỚC → Không match = KHÔNG gửi → Tiết kiệm cost!           │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Tại sao filter ở SNS tốt hơn filter ở SQS/Consumer?

Filter ở ConsumerFilter ở SNS
FlowSQS nhận TẤT CẢ → Consumer đọc rồi bỏSNS chỉ gửi message match
Cost❌ Tốn tiền SQS requests✅ Tiết kiệm
Load❌ Consumer xử lý message không cần✅ Giảm load

4.4 Cross-Region Fan-out

┌─────────────────────────────────────────────────────────────────┐
│              CROSS-REGION REPLICATION                           │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   US-EAST-1                           EU-WEST-1                 │
│   ┌──────────────┐                   ┌──────────────┐           │
│   │  SNS Topic   │ ───────Cross───→  │  SQS Queue   │           │
│   │              │     Region        │              │           │
│   └──────────────┘                   └──────────────┘           │
│         │                                   │                   │
│         ↓                                   ↓                   │
│   ┌──────────────┐                   ┌──────────────┐           │
│   │ Local SQS    │                   │ EU Consumer  │           │
│   └──────────────┘                   └──────────────┘           │
│                                                                 │
│   Use Cases:                                                    │
│   • Data replication across regions                             │
│   • Low-latency processing near users                           │
│   • Disaster recovery                                           │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

5. Spring Boot Integration

5.1 Spring Boot có thể nhận SNS messages?

Có! Nhưng có 2 cách:

┌──────────────────────────────────────────────────────────────────┐
│              SPRING BOOT + SNS                                   │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│   OPTION 1: SNS → HTTP Endpoint (Spring Boot expose API)         │
│   ┌─────────────────────────────────────────────────────────────┐│
│   │  SNS Topic ──PUSH──→ https://your-app.com/sns-endpoint      ││
│   │                           ↓                                 ││
│   │                    @PostMapping("/sns-endpoint")            ││
│   │                    public void handle(@RequestBody...)      ││
│   │                                                             ││
│   │  ⚠️ Cần public URL, xử lý subscription confirmation         ││
│   └─────────────────────────────────────────────────────────────┘│
│                                                                  │
│   OPTION 2: SNS → SQS → Spring Boot (RECOMMENDED!)               │
│   ┌─────────────────────────────────────────────────────────────┐│
│   │  SNS Topic ──→ SQS Queue ←── Spring Boot @SqsListener       ││
│   │                                                             ││
│   │  ✅ Better: decoupled, retry, DLQ support                   ││
│   │  ✅ No need for public URL                                  ││
│   │  ✅ Buffering when app is down                              ││
│   └─────────────────────────────────────────────────────────────┘│
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

5.2 Option 1: HTTP Endpoint

@RestController
public class SnsController {
 
    @PostMapping("/sns-endpoint")
    public ResponseEntity<String> handleSns(@RequestBody String payload,
                                            @RequestHeader("x-amz-sns-message-type") String messageType) {
        
        // 1. Handle subscription confirmation
        if ("SubscriptionConfirmation".equals(messageType)) {
            // Extract SubscribeURL and call it to confirm
            return ResponseEntity.ok("Subscribed");
        }
        
        // 2. Handle actual notifications
        if ("Notification".equals(messageType)) {
            // Process the message
            processMessage(payload);
        }
        
        return ResponseEntity.ok("OK");
    }
}
@Component
public class OrderEventConsumer {
 
    // SNS publishes to SQS, Spring Boot listens to SQS
    @SqsListener("order-events-queue")
    public void handleOrderEvent(String message) {
        // Message contains SNS wrapper, parse it
        SnsNotification notification = objectMapper.readValue(message, SnsNotification.class);
        String actualMessage = notification.getMessage();
        
        // Process the actual message
        processOrderEvent(actualMessage);
    }
}

5.4 So sánh các patterns

PatternProsCons
SNS → HTTPSimple, directNeed public URL, handle retries
SNS → SQS → AppDecoupled, buffering, DLQExtra hop, slight delay
SNS → LambdaServerless, auto-scaleCold start, 15 min timeout

6. FIFO Topics

5.1 FIFO Topic Features

┌─────────────────────────────────────────────────────────────────┐
│                   SNS FIFO TOPICS                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   Standard Topic:                                               │
│   • Best-effort ordering                                        │
│   • At-least-once delivery                                      │
│   • Unlimited throughput                                        │
│                                                                 │
│   FIFO Topic:                                                   │
│   • Strict ordering (by Message Group ID)                       │
│   • Exactly-once delivery                                       │
│   • 300 msg/s (or 10 MB/s with batching)                        │
│   • Name must end with ".fifo"                                  │
│                                                                 │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │  SNS FIFO Topic ──────→ SQS FIFO Queue ONLY             │   │
│   │  (Cannot subscribe to Standard SQS or Lambda)           │   │
│   └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

5.2 Message Group ID

┌─────────────────────────────────────────────────────────────────┐
│                  MESSAGE GROUP ID                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   Publisher sends with MessageGroupId:                          │
│                                                                 │
│   Group "user-123": [Order1] → [Order2] → [Order3]              │
│   Group "user-456": [Order1] → [Order2]                         │
│                                                                 │
│   Delivery guarantees:                                          │
│   • Messages trong SAME group → Ordered                         │
│   • Messages across groups → Parallel processing                │
│                                                                 │
│   FIFO Deduplication:                                           │
│   • Content-based: SNS auto-generates dedup ID                  │
│   • Message-based: You provide MessageDeduplicationId           │
│   • 5-minute deduplication window                               │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

6. Security

6.1 Encryption

┌──────────────────────────────────────────────────────────────────┐
│                       ENCRYPTION                                 │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│   IN-FLIGHT:                                                     │
│   • HTTPS endpoints required                                     │
│   • TLS for all API calls                                        │
│                                                                  │
│   AT-REST (SSE):                                                 │
│   • SSE-KMS for message encryption                               │
│   • Key: AWS managed or Customer managed CMK                     │
│   • Messages encrypted before stored (temporary)                 │
│                                                                  │
│   ⚠️  Note: SNS doesn't store messages long-term                 │
│       Encryption mostly for in-transit protection                │
│                                                                  │
└──────────────────────────────────────────────────────────────────┘

6.2 Access Control

┌─────────────────────────────────────────────────────────────────┐
│                    ACCESS CONTROL                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   IAM POLICIES:                                                 │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │  Control WHO can Publish/Subscribe                      │   │
│   │  Attached to IAM users/roles                            │   │
│   └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│   SNS ACCESS POLICIES (Resource-based):                         │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │  Attached to SNS topic                                  │   │
│   │  Allow cross-account publish/subscribe                  │   │
│   │  Allow AWS services (S3, CloudWatch)                    │   │
│   └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

SNS Access Policy Example (Allow S3 to publish):

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Service": "s3.amazonaws.com"},
    "Action": "sns:Publish",
    "Resource": "arn:aws:sns:region:account:topic",
    "Condition": {
      "ArnLike": {
        "aws:SourceArn": "arn:aws:s3:::my-bucket"
      }
    }
  }]
}

7. Best Practices

7.1 Design Patterns

PatternDescription
Fan-outSNS → Multiple SQS queues
Event-drivenSNS → Lambda
Cross-accountSNS topic in Account A, SQS in Account B
Cross-regionSNS topic in region A, SQS in region B

7.2 Message Filtering Best Practices

PracticeRecommendation
Filter at SNSDon't filter in Lambda/Consumer
Use MessageAttributesMore efficient than body filtering
Keep policies simpleComplex policies = slower processing

7.3 Reliability

┌─────────────────────────────────────────────────────────────────┐
│                  RELIABILITY TIPS                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   SNS → SQS:                                                    │
│   • Configure DLQ on SQS for failed messages                    │
│                                                                 │
│   SNS → Lambda:                                                 │
│   • Configure DLQ on Lambda                                     │
│   • Set appropriate retry count                                 │
│                                                                 │
│   SNS → HTTP:                                                   │
│   • SNS retries with exponential backoff                        │
│   • Configure DLQ on SNS subscription                           │
│   • 3 immediate retries + 23 retries over 3 hours               │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

7.4 Cost Optimization

StrategyDescription
Message FilteringReduce unnecessary deliveries
Batch PublishingPublishBatch API (up to 10 msgs)
Right ProtocolSQS cheaper than SMS for alerts

8. SNS vs SQS vs EventBridge

┌─────────────────────────────────────────────────────────────────┐
│            SNS vs SQS vs EVENTBRIDGE                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   SNS:                                                          │
│   • Pub/Sub, fan-out                                            │
│   • Simple message filtering                                    │
│   • Many subscription types                                     │
│   • No persistence                                              │
│                                                                 │
│   SQS:                                                          │
│   • Queue, point-to-point                                       │
│   • Message persistence                                         │
│   • Consumer polling                                            │
│   • No native fan-out                                           │
│                                                                 │
│   EventBridge:                                                  │
│   • Event bus                                                   │
│   • Advanced filtering (100+ rules)                             │
│   • Event transformation                                        │
│   • Schema registry                                             │
│   • Event replay                                                │
│   • Third-party integration                                     │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
FeatureSNSSQSEventBridge
ModelPub/SubQueueEvent Bus
FilteringSimple (attributes)NoneAdvanced (100+ rules)
PersistenceNoYesArchive/Replay
TargetsMany protocolsConsumer appsAWS services
TransformNoNoYes
Use CaseFan-outDecoupleEvent-driven

9. Common Exam Questions

Q1: SNS vs SQS delivery model?

A: SNS = Push to all subscribers. SQS = Consumer pulls messages, 1 per message.

Q2: SNS FIFO can subscribe to what?

A: Only SQS FIFO queues. Cannot subscribe to Lambda or Standard SQS.

Q3: Message filtering là gì?

A: Filter policy trên subscription để chỉ nhận messages matching criteria.

Q4: Max subscriptions per topic?

A: 12,500,000 subscriptions

Q5: SNS message max size?

A: 256 KB

Q6: How to ensure SQS receives from SNS?

A: Configure SQS access policy cho phép SNS topic gửi messages.


Tài liệu tham khảo