Skip to main content
AWSMessaging & Eventsintermediate

SQS vs SNS vs EventBridge

Compare Amazon SQS, SNS, and EventBridge for messaging, event routing, and building event-driven architectures on AWS.

CloudToolStack Team25 min readPublished Feb 22, 2026

Prerequisites

Event-Driven Architecture on AWS

Event-driven architecture (EDA) is a design pattern where services communicate by producing and consuming events rather than making direct synchronous calls. On AWS, three services form the backbone of event-driven systems: Amazon SQS (Simple Queue Service) for point-to-point message queuing, Amazon SNS (Simple Notification Service) for pub/sub messaging, and Amazon EventBridge for event routing with content-based filtering. Each service solves different messaging challenges, and production architectures frequently use all three together.

The fundamental benefit of EDA is decoupling. When Service A publishes an event instead of directly calling Service B, neither service needs to know about the other. Service A does not care how many consumers process the event or what they do with it. Service B does not care who produced the event. This decoupling enables teams to develop, deploy, and scale services independently, a key enabler for microservices architectures.

Event-driven systems also improve resilience. If a downstream service is temporarily unavailable, messages queue up in SQS and are processed when the service recovers. With synchronous architectures, the upstream service would fail or block. This buffering capability is what makes EDA particularly well-suited for handling traffic spikes, batch processing, and workflows where different steps have different processing speeds.

Events vs Messages vs Commands

These terms are often used interchangeably, but they have distinct meanings. An event is a notification that something happened ("OrderPlaced"), and the producer does not care who receives it. A command is a directed instruction ("ProcessPayment"), and there is a specific consumer expected to act on it. A message is the envelope that carries either an event or command. SNS and EventBridge are optimized for events (one-to-many). SQS is optimized for commands (point-to-point). Understanding this distinction helps you choose the right service.

Amazon SQS Deep Dive

Amazon SQS is a fully managed message queuing service that decouples producers from consumers. A producer sends a message to a queue, and a consumer polls the queue to receive and process messages. SQS guarantees that each message is delivered at least once (standard queues) or exactly once (FIFO queues), and messages persist in the queue until a consumer successfully processes and deletes them.

SQS is the simplest and most battle-tested messaging service on AWS. It scales automatically from zero to millions of messages per second with no provisioning required. It supports messages up to 256 KB in size (with an extended client library that supports up to 2 GB using S3), retention periods from 1 minute to 14 days, and visibility timeouts that prevent multiple consumers from processing the same message simultaneously.

Standard vs FIFO Queues

FeatureStandard QueueFIFO Queue
ThroughputVirtually unlimited300 msg/s (3,000 with batching, 70K with high throughput mode)
OrderingBest-effort orderingStrict ordering within message group
DeliveryAt-least-once (possible duplicates)Exactly-once processing
DeduplicationNot supportedContent-based or explicit dedup ID
Message GroupsNot applicableOrdered processing per group ID
Cost$0.40 per million requests$0.50 per million requests
Queue NameAny valid nameMust end with .fifo
sqs-operations.sh
# Create a standard queue with a dead-letter queue
aws sqs create-queue \
  --queue-name order-processing-dlq \
  --attributes '{
    "MessageRetentionPeriod": "1209600"
  }'

DLQ_ARN=$(aws sqs get-queue-attributes \
  --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/order-processing-dlq \
  --attribute-names QueueArn --query 'Attributes.QueueArn' --output text)

aws sqs create-queue \
  --queue-name order-processing \
  --attributes '{
    "VisibilityTimeout": "300",
    "MessageRetentionPeriod": "345600",
    "ReceiveMessageWaitTimeSeconds": "20",
    "RedrivePolicy": "{\"deadLetterTargetArn\":\"'$DLQ_ARN'\",\"maxReceiveCount\":\"3\"}"
  }'

# Create a FIFO queue with high-throughput mode
aws sqs create-queue \
  --queue-name order-processing.fifo \
  --attributes '{
    "FifoQueue": "true",
    "ContentBasedDeduplication": "true",
    "DeduplicationScope": "messageGroup",
    "FifoThroughputLimit": "perMessageGroupId"
  }'

# Send a message to a standard queue
aws sqs send-message \
  --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/order-processing \
  --message-body '{"orderId": "ord-123", "amount": 49.99}' \
  --message-attributes '{
    "OrderType": {"DataType": "String", "StringValue": "standard"},
    "Priority": {"DataType": "Number", "StringValue": "1"}
  }'

# Send a message to a FIFO queue
aws sqs send-message \
  --queue-url https://sqs.us-east-1.amazonaws.com/123456789012/order-processing.fifo \
  --message-body '{"orderId": "ord-123", "amount": 49.99}' \
  --message-group-id "customer-456" \
  --message-deduplication-id "ord-123-attempt-1"

Lambda SQS Integration

Lambda can poll SQS queues automatically via event source mappings. This is the most common pattern for processing SQS messages. Lambda handles the polling, batching, and deletion of successfully processed messages. You configure the batch size (1-10,000), batch window (0-300 seconds), and concurrency controls.

lambda-sqs-integration.yaml
Resources:
  OrderProcessorFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: order-processor
      Runtime: nodejs20.x
      Handler: index.handler
      Timeout: 300
      ReservedConcurrentExecutions: 10
      Code:
        ZipFile: |
          exports.handler = async (event) => {
            const failedMessageIds = [];
            for (const record of event.Records) {
              try {
                const order = JSON.parse(record.body);
                console.log('Processing order:', order.orderId);
                // Process the order...
              } catch (error) {
                console.error('Failed to process:', record.messageId, error);
                failedMessageIds.push(record.messageId);
              }
            }
            // Return partial batch failure response
            return {
              batchItemFailures: failedMessageIds.map(id => ({
                itemIdentifier: id
              }))
            };
          };

  OrderQueueEventSource:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      EventSourceArn: !GetAtt OrderQueue.Arn
      FunctionName: !Ref OrderProcessorFunction
      BatchSize: 10
      MaximumBatchingWindowInSeconds: 5
      FunctionResponseTypes:
        - ReportBatchItemFailures
      ScalingConfig:
        MaximumConcurrency: 10

Always Enable Partial Batch Failure Reporting

Without ReportBatchItemFailures, if any message in a batch fails, the entire batch is retried, including messages that were already processed successfully. This leads to duplicate processing and wasted compute. With partial batch failure reporting, only the failed messages are retried. This is critical for idempotent processing and cost efficiency.

Amazon SNS Deep Dive

Amazon SNS is a fully managed pub/sub messaging service. A publisher sends a message to an SNS topic, and SNS delivers copies of that message to all subscribers of the topic. Subscribers can be SQS queues, Lambda functions, HTTP/HTTPS endpoints, email addresses, SMS numbers, or mobile push notifications. This one-to-many delivery pattern is calledfan-out.

SNS supports message filtering, so subscribers can specify filter policies that determine which messages they receive based on message attributes. This lets you use a single topic for multiple event types while ensuring each subscriber only receives relevant messages.

SNS Message Filtering

sns-filter-policy.json
{
  "Comment": "This filter policy routes only high-value orders to the premium processor",
  "FilterPolicy": {
    "order_type": ["premium", "enterprise"],
    "amount": [{"numeric": [">=", 1000]}],
    "region": [{"anything-but": ["test"]}]
  },
  "FilterPolicyScope": "MessageAttributes"
}

// Alternative: filter on message body (JSON payload)
{
  "FilterPolicy": {
    "detail": {
      "order": {
        "type": ["premium", "enterprise"],
        "amount": [{"numeric": [">=", 1000]}]
      }
    }
  },
  "FilterPolicyScope": "MessageBody"
}

Filter policies support several comparison operators: exact string match, string prefix match, numeric comparisons (>=, <=, =, numeric range), anything-but (exclusion), and exists (presence check). Message body filtering was added in 2022 and allows filtering on nested JSON fields in the message payload, eliminating the need to duplicate data in message attributes.

SNS FIFO Topics

Like SQS, SNS also offers FIFO topics that guarantee strict ordering and exactly-once delivery to subscribers. FIFO topics can only deliver to FIFO SQS queues, and they do not support Lambda, HTTP, email, or SMS subscribers. This makes them ideal for ordered fan-out scenarios where you need the same ordered stream delivered to multiple processing pipelines.

bash
# Create an SNS FIFO topic
aws sns create-topic \
  --name order-events.fifo \
  --attributes '{
    "FifoTopic": "true",
    "ContentBasedDeduplication": "true"
  }'

# Subscribe a FIFO SQS queue to the FIFO topic
aws sns subscribe \
  --topic-arn arn:aws:sns:us-east-1:123456789012:order-events.fifo \
  --protocol sqs \
  --notification-endpoint arn:aws:sqs:us-east-1:123456789012:analytics-pipeline.fifo \
  --attributes '{
    "FilterPolicy": "{\"event_type\": [\"OrderCreated\", \"OrderShipped\"]}",
    "RawMessageDelivery": "true"
  }'

Amazon EventBridge Deep Dive

Amazon EventBridge is the most feature-rich event routing service on AWS. Unlike SNS (which routes based on topic subscriptions and simple attribute filters), EventBridge routes events based on sophisticated content-based rules that can match any field in the event payload. EventBridge also provides native integration with over 100 AWS services as event sources, over 20 AWS services as targets, and a growing catalog of third-party SaaS integrations (Shopify, Datadog, PagerDuty, Zendesk, and more).

EventBridge uses the concept of an event bus, a pipeline that receives events and routes them to targets based on rules. Every AWS account has a default event bus that receives events from AWS services automatically. You can create custom event buses for your application events and partner event buses for SaaS integrations.

eventbridge-rule.yaml
Resources:
  # Custom event bus for application events
  OrderEventBus:
    Type: AWS::Events::EventBus
    Properties:
      Name: order-events

  # Rule to route order events to Lambda
  HighValueOrderRule:
    Type: AWS::Events::Rule
    Properties:
      Name: high-value-orders
      EventBusName: !Ref OrderEventBus
      EventPattern:
        source:
          - "com.myapp.orders"
        detail-type:
          - "OrderPlaced"
        detail:
          amount:
            - numeric: [">=", 500]
          status:
            - "confirmed"
          shipping:
            country:
              - anything-but: ["XX", "YY"]
      Targets:
        - Arn: !GetAtt HighValueOrderProcessor.Arn
          Id: "HighValueProcessor"
          RetryPolicy:
            MaximumRetryAttempts: 3
            MaximumEventAgeInSeconds: 3600
          DeadLetterConfig:
            Arn: !GetAtt EventBridgeDLQ.Arn
        - Arn: !GetAtt NotificationQueue.Arn
          Id: "NotificationQueue"
          InputTransformer:
            InputPathsMap:
              orderId: "$.detail.orderId"
              amount: "$.detail.amount"
              customer: "$.detail.customerEmail"
            InputTemplate: >
              "High-value order <orderId> for $<amount> from <customer>"

  # Rule for scheduled events (cron-like)
  DailyReportRule:
    Type: AWS::Events::Rule
    Properties:
      Name: daily-order-report
      ScheduleExpression: "cron(0 8 * * ? *)"
      State: ENABLED
      Targets:
        - Arn: !GetAtt ReportGeneratorFunction.Arn
          Id: "DailyReport"

Putting Events to EventBridge

put-events.ts
import { EventBridgeClient, PutEventsCommand } from "@aws-sdk/client-eventbridge";

const client = new EventBridgeClient({ region: "us-east-1" });

// Publish an application event
async function publishOrderEvent(order: {
  orderId: string;
  amount: number;
  customerEmail: string;
  status: string;
}) {
  const command = new PutEventsCommand({
    Entries: [
      {
        EventBusName: "order-events",
        Source: "com.myapp.orders",
        DetailType: "OrderPlaced",
        Detail: JSON.stringify({
          orderId: order.orderId,
          amount: order.amount,
          customerEmail: order.customerEmail,
          status: order.status,
          timestamp: new Date().toISOString(),
        }),
        // Optional: trace context for X-Ray integration
        TraceHeader: process.env._X_AMZN_TRACE_ID,
      },
    ],
  });

  const response = await client.send(command);

  // Check for failed entries (partial failures are possible)
  if (response.FailedEntryCount && response.FailedEntryCount > 0) {
    console.error("Some events failed:", response.Entries?.filter(e => e.ErrorCode));
    // Implement retry logic for failed entries
  }

  return response;
}

EventBridge Payload Limit

EventBridge events have a maximum payload size of 256 KB. For larger payloads, store the data in S3 and include only the S3 key in the event. This "claim check" pattern is common in event-driven architectures. Also note that PutEvents supports batching up to 10 events per API call, which reduces costs and improves throughput.

SQS vs SNS vs EventBridge Comparison

Choosing between SQS, SNS, and EventBridge depends on your messaging pattern, delivery requirements, and integration needs. Here is a comprehensive comparison:

FeatureSQSSNSEventBridge
PatternPoint-to-point queuePub/sub fan-outEvent bus with content routing
DeliveryPull (consumer polls)Push (SNS delivers)Push (EventBridge delivers)
Consumers per message1 (single consumer)Up to 12.5M subscribers/topicUp to 5 targets per rule
FilteringNone (consumer processes all)Attribute-based filter policiesContent-based rules (any JSON field)
Message retention1 min to 14 daysNo retention (immediate delivery)No retention (24h retry with DLQ)
OrderingFIFO queues (strict ordering)FIFO topics (strict ordering)No ordering guarantee
Max message size256 KB (2 GB with S3)256 KB (2 GB with S3)256 KB
ThroughputVirtually unlimitedVirtually unlimitedSoft limit of 10K events/sec (adjustable)
Schema validationNoNoYes (Schema Registry)
Replay capabilityNoNoYes (Event Archive & Replay)
SaaS integrationsNoNoYes (100+ partners)
Cost modelPer request ($0.40/million)Per publish + deliveryPer event published ($1.00/million)

Decision Framework

Use SQS when you need reliable point-to-point delivery, message buffering, or rate limiting between a producer and a single consumer. UseSNS when you need simple fan-out to multiple subscribers with attribute-based filtering. Use EventBridge when you need content-based routing, schema validation, event replay, SaaS integrations, or complex routing rules. In practice, many architectures combine all three: EventBridge routes events to SNS topics for fan-out, and SNS delivers to SQS queues for buffered consumption.

Fan-Out & Choreography Patterns

Fan-out is the pattern of delivering a single event to multiple consumers. AWS supports several fan-out patterns, each with different trade-offs.

SNS Fan-Out to SQS

The classic AWS fan-out pattern publishes to an SNS topic with multiple SQS queues subscribed. Each queue receives a copy of every message (or filtered messages with filter policies). Each queue is processed independently by its own consumer. This pattern provides reliable delivery with independent processing speeds and failure isolation.

fan-out-pattern.yaml
Resources:
  OrderTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: order-events

  # Each downstream service has its own SQS queue
  InventoryQueue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: inventory-updates
      RedrivePolicy:
        deadLetterTargetArn: !GetAtt InventoryDLQ.Arn
        maxReceiveCount: 3

  AnalyticsQueue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: analytics-events
      RedrivePolicy:
        deadLetterTargetArn: !GetAtt AnalyticsDLQ.Arn
        maxReceiveCount: 3

  NotificationQueue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: customer-notifications
      RedrivePolicy:
        deadLetterTargetArn: !GetAtt NotificationDLQ.Arn
        maxReceiveCount: 3

  # Subscribe each queue to the topic with filters
  InventorySubscription:
    Type: AWS::SNS::Subscription
    Properties:
      TopicArn: !Ref OrderTopic
      Protocol: sqs
      Endpoint: !GetAtt InventoryQueue.Arn
      RawMessageDelivery: true
      FilterPolicy:
        event_type:
          - OrderPlaced
          - OrderCancelled

  AnalyticsSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      TopicArn: !Ref OrderTopic
      Protocol: sqs
      Endpoint: !GetAtt AnalyticsQueue.Arn
      RawMessageDelivery: true
      # No filter - analytics receives ALL events

  NotificationSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      TopicArn: !Ref OrderTopic
      Protocol: sqs
      Endpoint: !GetAtt NotificationQueue.Arn
      RawMessageDelivery: true
      FilterPolicy:
        event_type:
          - OrderShipped
          - OrderDelivered
        notification_preference:
          - exists: true

EventBridge Choreography

In a choreography pattern, services react to events independently without a central orchestrator. Each service publishes events about its own state changes, and other services subscribe to the events they care about. EventBridge acts as the central event bus, routing events based on content-based rules. This pattern scales well and reduces coupling, but can be harder to debug because there is no single place that defines the full workflow.

Dead-Letter Queues & Error Handling

Dead-letter queues (DLQs) are essential for production messaging systems. When a message cannot be processed after a configured number of attempts, it is moved to a DLQ instead of being lost or retried indefinitely. DLQs prevent poison messages from blocking the queue and give you a mechanism to inspect, debug, and reprocess failed messages.

DLQ Patterns by Service

ServiceDLQ MechanismConfiguration
SQSRedrive policy on source queuemaxReceiveCount then move to DLQ
SNSRedrive policy on subscriptionFailed deliveries after all retries go to SQS DLQ
EventBridgeDLQ on rule targetFailed deliveries after retry policy go to SQS DLQ
Lambda (async)DLQ or on-failure destinationAfter max retry attempts (0-2), send to SQS/SNS
dlq-monitoring.sh
# Monitor DLQ depth with CloudWatch alarm
aws cloudwatch put-metric-alarm \
  --alarm-name "dlq-messages-detected" \
  --namespace "AWS/SQS" \
  --metric-name "ApproximateNumberOfMessagesVisible" \
  --dimensions Name=QueueName,Value=order-processing-dlq \
  --statistic Sum \
  --period 60 \
  --evaluation-periods 1 \
  --threshold 1 \
  --comparison-operator GreaterThanOrEqualToThreshold \
  --alarm-actions "arn:aws:sns:us-east-1:123456789012:ops-alerts"

# Redrive messages from DLQ back to source queue (SQS DLQ redrive)
aws sqs start-message-move-task \
  --source-arn "arn:aws:sqs:us-east-1:123456789012:order-processing-dlq" \
  --destination-arn "arn:aws:sqs:us-east-1:123456789012:order-processing" \
  --max-number-of-messages-per-second 10

# Check redrive task status
aws sqs list-message-move-tasks \
  --source-arn "arn:aws:sqs:us-east-1:123456789012:order-processing-dlq"

DLQ Alarms Are Non-Negotiable

Every DLQ must have a CloudWatch alarm that fires whenApproximateNumberOfMessagesVisible exceeds zero. Messages in a DLQ represent data that was not processed. This could mean lost orders, missed notifications, or stale inventory. Without DLQ monitoring, you will not know about processing failures until a customer complains. Set up an alarm, a runbook for investigation, and a process for redriving messages after the root cause is fixed.

Event Schema Registry & Validation

Amazon EventBridge Schema Registry automatically discovers and stores the schema (structure) of events flowing through your event buses. When you publish events, EventBridge can infer the schema and add it to the registry. You can also define schemas manually using JSON Schema or OpenAPI formats. Schemas are versioned, so you can track how your event formats evolve over time.

The Schema Registry provides code bindings: you can download generated code in Java, Python, TypeScript, or Go that provides strongly typed classes for your events. This eliminates manual parsing and reduces bugs caused by schema mismatches between producers and consumers.

schema-definition.json
{
  "openapi": "3.0.0",
  "info": {
    "title": "OrderPlaced",
    "version": "1.0.0"
  },
  "paths": {},
  "components": {
    "schemas": {
      "OrderPlaced": {
        "type": "object",
        "required": ["orderId", "customerId", "amount", "items", "timestamp"],
        "properties": {
          "orderId": {
            "type": "string",
            "pattern": "^ord-[a-zA-Z0-9]{8}$"
          },
          "customerId": {
            "type": "string"
          },
          "amount": {
            "type": "number",
            "minimum": 0.01
          },
          "currency": {
            "type": "string",
            "enum": ["USD", "EUR", "GBP"],
            "default": "USD"
          },
          "items": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "required": ["productId", "quantity", "price"],
              "properties": {
                "productId": { "type": "string" },
                "quantity": { "type": "integer", "minimum": 1 },
                "price": { "type": "number", "minimum": 0 }
              }
            }
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    }
  }
}

Event Versioning Strategies

As your system evolves, event schemas will change. There are three common strategies for handling schema evolution:

Backward compatible changes add new optional fields without removing or renaming existing fields. Existing consumers ignore the new fields. This is the safest approach and should be the default strategy.

Versioned events publish different versions of the same event type (e.g., OrderPlaced.v1, OrderPlaced.v2). Consumers subscribe to the version they support. This is useful for breaking changes but increases complexity.

Event adapters use a Lambda function to transform events from one schema version to another. The adapter subscribes to the new schema and publishes a transformed event in the old schema for legacy consumers. This is a bridge strategy during migrations.

Performance Tuning & Scaling

Each messaging service has different scaling characteristics and tuning levers. Understanding these is critical for building systems that handle production traffic reliably.

SQS Performance Tuning

SQS standard queues scale automatically. The key tuning parameters areVisibilityTimeout (set to 6x your processing time to handle retries),ReceiveMessageWaitTimeSeconds (set to 20 for long polling to reduce empty receives and API costs), and batch operations (send/receive/delete in batches of 10 to reduce API calls by 90%).

EventBridge Throughput

EventBridge has a default soft limit of 10,000 events per second per region per account (on the default bus). Custom event buses share this limit. For high-throughput scenarios, request a limit increase through AWS Support. EventBridge also supports batching viaPutEvents with up to 10 entries per call.

batch-operations.ts
import { SQSClient, SendMessageBatchCommand } from "@aws-sdk/client-sqs";

const sqs = new SQSClient({ region: "us-east-1" });

// Batch send up to 10 messages at once (reduces API calls by 90%)
async function batchSendOrders(orders: Array<{ orderId: string; amount: number }>) {
  const entries = orders.slice(0, 10).map((order, index) => ({
    Id: `msg-${index}`,
    MessageBody: JSON.stringify(order),
    MessageAttributes: {
      OrderType: {
        DataType: "String",
        StringValue: order.amount >= 500 ? "premium" : "standard",
      },
    },
  }));

  const command = new SendMessageBatchCommand({
    QueueUrl: "https://sqs.us-east-1.amazonaws.com/123456789012/order-processing",
    Entries: entries,
  });

  const response = await sqs.send(command);

  if (response.Failed && response.Failed.length > 0) {
    console.error("Failed messages:", response.Failed);
    // Implement retry for failed entries
  }

  return response;
}

Best Practices & Architecture Patterns

Building reliable event-driven systems requires careful attention to idempotency, ordering, error handling, and observability. The following patterns represent battle-tested approaches used in production AWS environments.

Idempotent Consumers

With at-least-once delivery (standard SQS, SNS, EventBridge), your consumers must handle duplicate messages gracefully. The most common approach is to store a hash or ID of each processed message in DynamoDB with a conditional write. If the write fails because the ID already exists, the message was already processed and can be safely skipped.

The Transactional Outbox Pattern

A common challenge in event-driven systems is ensuring that a database write and an event publication happen atomically. If you write to DynamoDB and then publish to EventBridge, either operation could fail independently. The transactional outbox pattern solves this by writing both the business data and the event to the same DynamoDB table in a single transaction. A separate process (DynamoDB Streams + Lambda) reads the outbox and publishes events to EventBridge, retrying on failure.

Event Replay with EventBridge Archive

EventBridge Archive and Replay is a unique capability that neither SQS nor SNS offers. You can archive all events (or filtered events) flowing through an event bus and replay them later. This is invaluable for disaster recovery (replay events to rebuild state), testing (replay production events against a new version), and debugging (replay the exact sequence of events that caused a bug). Archives are stored in S3 and billed at S3 storage rates.

Choosing the Right Pattern

Request-response (synchronous): Use API Gateway + Lambda when the caller needs an immediate response. Reserve for user-facing APIs where latency matters.

Queue-based load leveling: Use SQS between a fast producer and a slow consumer to absorb traffic spikes. The queue acts as a buffer, smoothing out bursts.

Fan-out: Use SNS + SQS when one event needs to trigger multiple independent downstream processes.

Event routing: Use EventBridge when you need content-based routing, schema validation, or SaaS integrations.

Workflow orchestration: Use Step Functions when you need a defined sequence of steps with error handling, retries, and conditional branching. Step Functions complement event-driven patterns by orchestrating complex multi-step processes.

Lambda Performance Tuning: Optimizing Event-Driven Lambda FunctionsMulti-Cloud Messaging: Comparing AWS, Azure & GCP Event Services

Key Takeaways

  1. 1SQS is best for point-to-point decoupling with guaranteed delivery and message retention.
  2. 2SNS is best for fan-out pub/sub where one message must reach multiple subscribers.
  3. 3EventBridge is best for event routing with content-based filtering and schema management.
  4. 4FIFO queues provide exactly-once processing and strict ordering for critical workflows.
  5. 5Dead-letter queues are essential for handling failed messages across all three services.
  6. 6Combining services (SNS + SQS fan-out, EventBridge + SQS) is a common best practice.

Frequently Asked Questions

When should I use SQS vs SNS?
Use SQS when you need a queue for point-to-point communication with guaranteed delivery, retry logic, and message retention. Use SNS when you need to broadcast a message to multiple subscribers (fan-out). They are often used together: SNS for fan-out, with SQS queues as subscribers.
What is EventBridge and how does it differ from SNS?
EventBridge is an event bus for routing events based on content. Unlike SNS which uses topic-based filtering, EventBridge matches events against rules using field-level patterns. EventBridge also has a schema registry, archive/replay, and native integrations with 30+ AWS services and SaaS partners.
What is the difference between SQS Standard and FIFO?
Standard queues offer at-least-once delivery with best-effort ordering and nearly unlimited throughput. FIFO queues guarantee exactly-once processing and strict message ordering within message groups, but are limited to 300-3,000 messages per second.
How do dead-letter queues work?
A dead-letter queue (DLQ) receives messages that fail processing after a configured number of retries (maxReceiveCount). It prevents poison messages from blocking the main queue. All three services support DLQs. You should monitor DLQ depth and set up alerts.
Can I use EventBridge for cross-account events?
Yes. EventBridge supports cross-account event delivery by allowing other accounts to put events on your event bus or by sending events to event buses in other accounts. This enables centralized event processing in multi-account architectures.

Written by CloudToolStack Team

Cloud engineers and architects with hands-on experience across AWS, Azure, and GCP. We write guides based on real-world production patterns, not just documentation rewrites.

Disclaimer: This guide is for educational purposes. Cloud services change frequently; always refer to official documentation for the latest information. AWS, Azure, and GCP are trademarks of their respective owners.