Messaging and Integration
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. See the section bibliography for the reference material consulted while preparing these pages. |
This page covers the AWS services that let one part of an application hand work or facts to another without waiting
for it: queues (Amazon SQS), publish/subscribe topics (Amazon SNS), event routers (Amazon EventBridge), workflow
orchestration (AWS Step Functions) and, more briefly, the managed brokers and streams (Amazon MQ, Amazon MSK, Amazon
Kinesis). Commands are current for AWS CLI v2 (2.37 line), the AWS SDK for Java 2.x and Spring Cloud AWS 4.x (Spring
Boot 4) or 3.4.x (Spring Boot 3.5); quotas, versions and console names were checked against the official
documentation on 2026-10-01 and should be re-verified with aws --version and the linked pages before you rely on
exact numbers. Examples use the placeholder Region us-east-1 and the placeholder account ID 111122223333.
In the running Bookshelf scenario, orders-api accepts an order and must tell several other parties: the
notifier worker that sends the confirmation email (see SES email), an archive and
analytics consumer, and eventually a fulfilment workflow. Calling each of them synchronously would make order
placement as slow and as fragile as the slowest dependency. Instead orders-api publishes one event and every
interested party consumes it at its own pace. The notifier is fed from the SQS queue notifier-queue (with its
dead-letter queue notifier-dlq) that the Lambda page already wires to a function; this page shows where that queue
comes from and how events reach it. For the Lambda side see
Lambda: event-driven and serverless apps.
The protocol and pattern theory behind these services is not repeated here; it lives in messaging models and patterns, delivery guarantees and messaging protocols. For the Azure counterparts (Service Bus, Event Grid, Event Hubs) see the Azure section starting at Azure.
Choosing between the services
The first decision is what you are sending. A command tells one consumer to do something and expects it to be done eventually; an event states that something happened and may interest zero, one or many consumers; a stream is an ordered, replayable log that many consumers read at their own offsets.
| Service | Model | Typical use | Delivery and ordering |
|---|---|---|---|
SQS |
Pull-based queue; each message is processed by one consumer of the queue |
Work queues, buffering, decoupling a producer from a slow consumer, the |
Standard: at least once, best-effort ordering. FIFO: exactly-once processing within the deduplication window, strict order per message group |
SNS |
Push-based topic; each message goes to every subscriber (optionally filtered) |
Fan-out of one event to queues, Lambda functions, HTTP endpoints, email and SMS |
Standard: at least once, best-effort ordering. FIFO topics: ordering and deduplication, FIFO queue subscribers only |
EventBridge event bus |
Content-based router with rules (Classic) or subscribers (Custom Event Bus) |
Routing AWS service events and your own application events to many targets, cross-account |
At least once; the Custom Event Bus adds retention, ordered (FIFO) delivery per event group and replay |
EventBridge Pipes |
Point-to-point pipeline: source, filter, enrichment, target |
Connecting a queue or stream to a target without glue code |
Follows the source’s semantics |
Step Functions |
State machine orchestrating many steps |
Multi-step flows with retries, branching, waiting and compensation |
Standard: exactly-once state execution; Express: at-least-once (asynchronous) or at-most-once (synchronous) |
Kinesis Data Streams |
Partitioned, replayable log; many consumers |
High-volume ordered ingestion (clickstreams, telemetry), real-time analytics |
Ordered per shard, retention 24 hours to 365 days |
MSK |
Apache Kafka, managed |
Existing Kafka applications and ecosystem |
Kafka semantics, ordered per partition |
Amazon MQ |
Managed ActiveMQ or RabbitMQ brokers |
Lift-and-shift of JMS, AMQP or MQTT applications |
Broker semantics |
A rule of thumb for new work on AWS: start with SQS when one consumer group must process each message, add SNS or EventBridge in front when several consumers need the same message, use Step Functions when the order of steps matters, and reach for Kinesis or MSK when you need a replayable log. Choose Amazon MQ only to migrate an application that already speaks JMS or AMQP; its brokers are provisioned and billed by the hour, unlike the serverless services above.
The Bookshelf order flow combines them: orders-api publishes OrderPlaced to an SNS topic, the topic fans out to two
SQS queues, and each queue has its own consumer and its own dead-letter queue.
publishes OrderPlaced"] --> T(("SNS topic
bookshelf-order-events")) T -->|"eventType = OrderPlaced"| Q1["SQS notifier-queue"] T -->|"all events"| Q2["SQS order-archive-queue"] Q1 --> N["notifier
Lambda or container"] N --> SES["Amazon SES
confirmation email"] Q2 --> A["archive consumer"] Q1 -. "after 5 failed receives" .-> D1["notifier-dlq"] Q2 -. "after 5 failed receives" .-> D2["order-archive-dlq"]
Amazon SQS
Amazon Simple Queue Service is a fully managed message queue. Producers send messages; consumers poll, process and then delete them. The queue stores each message redundantly across Availability Zones until it is deleted or its retention period expires, so a consumer outage never loses work.
Standard and FIFO queues
| Aspect | Standard queue | FIFO queue |
|---|---|---|
Throughput |
Nearly unlimited API calls per second |
300 transactions per second per API action per partition, or 3,000 messages per second with batching; high-throughput mode raises this to tens of thousands of transactions per second in the busiest Regions (limits vary by Region) |
Ordering |
Best effort; messages can arrive out of order |
Strict order within a message group ( |
Duplicates |
At-least-once delivery; occasional duplicates |
Deduplicated for 5 minutes by |
Name |
Any |
Must end in |
Scaling consumers |
Any number of concurrent consumers |
Concurrency is limited by the number of active message groups |
Use it for |
Work distribution where order does not matter and handlers are idempotent |
Per-entity ordering (all events of one order, one account) and no duplicates |
Fair queues are a standard-queue feature: when you set a MessageGroupId on messages sent to a standard queue, SQS
mitigates the noisy-neighbour problem by keeping the dwell time of quiet groups low while a busy group has a backlog. Use
them for multi-tenant queues where one tenant could otherwise starve the others.
Limits worth knowing (checked 2026-10-01): a message is at most 1 MiB (1,048,576 bytes); larger payloads go to S3 and the message carries a pointer, which the SQS Extended Client Library for Java automates up to 2 GB. Retention defaults to 4 days and can be 1 minute to 14 days. A message can carry up to 10 attributes, and a batch call handles at most 10 messages. Older guides and tutorials still quote a 256 KiB message limit, which was raised to 1 MiB in 2025.
Visibility timeout, long polling and delay
When a consumer receives a message, SQS does not remove it; it hides it for the visibility timeout (default 30
seconds, minimum 0, maximum 12 hours). If the consumer deletes the message within that time, it is gone. If the
consumer crashes or is too slow, the message becomes visible again and another consumer receives it. This is what
makes delivery at least once, and why consumers must be idempotent. Set the visibility timeout comfortably above the
longest processing time (for a Lambda consumer, at least the function timeout; the Lambda page recommends about six
times), or extend it for long jobs with change-message-visibility.
Short polling returns immediately, often empty, and every empty response is a billed request. Long polling waits up
to 20 seconds for a message (ReceiveMessageWaitTimeSeconds, or --wait-time-seconds per call) and is the setting to
use almost everywhere: fewer empty receives, lower cost, lower latency. Delay queues (DelaySeconds, up to 15
minutes) hide new messages for a while, and per-message timers do the same for individual messages on standard queues.
Dead-letter queues and redrive
A dead-letter queue (DLQ) is an ordinary SQS queue of the same type (standard or FIFO) that receives messages the
source queue could not get processed. The source queue’s redrive policy names the DLQ and maxReceiveCount, the number
of receives after which a message is moved. Practical rules:
-
Set the DLQ retention period longer than the source queue’s, because the original enqueue time is preserved and the clock keeps running; a message can otherwise expire in the DLQ before anyone looks at it.
-
Choose
maxReceiveCountof about 5 or more so transient errors and throttling do not dead-letter healthy messages. -
Alarm on the DLQ metric
ApproximateNumberOfMessagesVisiblegreater than zero. -
After fixing the bug, redrive the messages back to the source queue (the console’s Start DLQ redrive action, or
start-message-move-task) instead of writing a one-off script.
In the AWS Management Console
-
Select the Region in the top bar (the examples assume
us-east-1), open Amazon SQS, then Queues, Create queue. -
Under Type choose Standard (or FIFO, which fixes the name suffix
.fifo), and name the dead-letter queuenotifier-dlq. Keep the defaults, set Message retention period to 14 days, and choose Create queue. -
Create the source queue
notifier-queue: set Visibility timeout to 3 minutes, Receive message wait time to 20 seconds, and under Dead-letter queue choose Enabled, selectnotifier-dlqand set Maximum receives to 5. -
Leave Encryption on its default (SQS-managed encryption is on by default; choose AWS KMS key when you need to audit or restrict key use; see Secrets Manager, Parameter Store and KMS).
-
To test, open
notifier-queue, choose Send and receive messages, type a body, Send message, then Poll for messages. To redrive later, opennotifier-dlqand choose Start DLQ redrive.
The same flow can run from AWS CloudShell, which already has credentials and the AWS CLI.
With the AWS CLI
export AWS_REGION=us-east-1
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
# Dead-letter queue first, with long retention (14 days = 1209600 seconds)
DLQ_URL=$(aws sqs create-queue --queue-name notifier-dlq \
--attributes MessageRetentionPeriod=1209600 --query QueueUrl --output text)
DLQ_ARN=$(aws sqs get-queue-attributes --queue-url "$DLQ_URL" \
--attribute-names QueueArn --query Attributes.QueueArn --output text)
# Source queue: visibility timeout, long polling and the redrive policy
cat > notifier-queue-attrs.json <<JSON
{
"VisibilityTimeout": "180",
"ReceiveMessageWaitTimeSeconds": "20",
"RedrivePolicy": "{\"deadLetterTargetArn\":\"$DLQ_ARN\",\"maxReceiveCount\":\"5\"}"
}
JSON
QUEUE_URL=$(aws sqs create-queue --queue-name notifier-queue \
--attributes file://notifier-queue-attrs.json --query QueueUrl --output text)
# Send, receive, delete
aws sqs send-message --queue-url "$QUEUE_URL" \
--message-body '{"orderId":"o-1001","email":"reader@example.com"}'
aws sqs receive-message --queue-url "$QUEUE_URL" --wait-time-seconds 10 \
--max-number-of-messages 5 --query 'Messages[].[MessageId,ReceiptHandle,Body]' --output text
aws sqs delete-message --queue-url "$QUEUE_URL" --receipt-handle "<receipt-handle>"
# FIFO queue: name ends in .fifo, content-based deduplication on
aws sqs create-queue --queue-name orders.fifo \
--attributes FifoQueue=true,ContentBasedDeduplication=true
aws sqs send-message --queue-url "https://sqs.$AWS_REGION.amazonaws.com/$ACCOUNT_ID/orders.fifo" \
--message-body '{"orderId":"o-1001","status":"PLACED"}' --message-group-id o-1001
# Redrive dead-lettered messages back to their source queue
aws sqs start-message-move-task --source-arn "$DLQ_ARN"
aws sqs list-message-move-tasks --source-arn "$DLQ_ARN"
Using SQS from Java
With Spring Boot, the Spring Cloud AWS SQS starter (io.awspring.cloud:spring-cloud-aws-starter-sqs, from the Spring Cloud
AWS 4.x BOM for Boot 4 or 3.4.x for Boot 3.5) provides SqsTemplate for sending and @SqsListener for consuming. The
credentials come from the default provider chain (task role, Pod Identity, instance profile), never from properties;
only the Region needs configuring (spring.cloud.aws.region.static=us-east-1).
package com.example.bookshelf.notifier;
import io.awspring.cloud.sqs.annotation.SqsListener;
import io.awspring.cloud.sqs.operations.SqsTemplate;
import org.springframework.stereotype.Component;
@Component
public class OrderQueue {
private final SqsTemplate sqs;
public OrderQueue(SqsTemplate sqs) {
this.sqs = sqs;
}
/** Producer side: send a JSON-serialisable payload to the queue. */
public void enqueue(OrderPlaced event) {
sqs.send(to -> to.queue("notifier-queue").payload(event));
}
/**
* Consumer side: the message is deleted only if the method returns normally, so an exception
* makes it visible again after the visibility timeout and eventually moves it to the DLQ.
*/
@SqsListener("notifier-queue")
public void onOrderPlaced(OrderPlaced event) {
// must be idempotent: the same message can be delivered more than once
sendConfirmationEmail(event);
}
private void sendConfirmationEmail(OrderPlaced event) {
// see the SES page for the sending code
}
public record OrderPlaced(String orderId, String email) { }
}
This is the container alternative to the Lambda notifier: the same queue can be consumed by an ECS service or an EKS
deployment, and scaled on queue depth (Application Auto Scaling on ECS, KEDA on EKS; see
ECS deployments, scaling and networking and
EKS microservices). For Quarkus, the SmallRye Reactive Messaging connectors in
Messaging with SmallRye Reactive Messaging speak Kafka, AMQP and JMS, which maps to
MSK and Amazon MQ below; for SQS itself use the Quarkiverse Amazon SQS extension or the AWS SDK client directly. Spring’s
view of messaging is in Spring Boot messaging overview. See the
Spring Cloud AWS reference.
Amazon SNS
Amazon Simple Notification Service publishes a message to a topic and delivers a copy to every subscription. Subscriber protocols include SQS queues, Lambda functions, Amazon Data Firehose, HTTP(S) endpoints, email, and SMS or mobile push (the latter through the AWS End User Messaging service, which replaces Amazon Pinpoint, whose end of support is 2026-10-30). Topics are standard (high throughput, at-least-once, best-effort ordering) or FIFO (ordering and deduplication, with SQS FIFO queues as subscribers; message archiving and replay are available for FIFO topics).
The pattern that matters most for application decoupling is SNS-to-SQS fan-out: the topic is the single publish point, each consumer owns an SQS queue subscribed to it, and a slow or failing consumer never affects the others because each queue buffers and dead-letters independently.
-
Filter policies let a subscriber receive only the messages it wants. A policy matches on message attributes (the default scope) or, with the
MessageBodyfilter policy scope, on fields of a JSON body. Messages that do not match are not delivered and are not billed as deliveries to that subscriber. -
Raw message delivery (
RawMessageDelivery=true) delivers the original body to SQS instead of an SNS JSON envelope, so a consumer can read the same payload whether it came from the topic or was sent straight to the queue. -
The queue needs a resource policy that allows the topic to send to it; without it the subscription is created but nothing arrives.
-
The maximum SNS message size is 256 KiB (checked 2026-10-01; the SNS Extended Client Library handles larger payloads through S3), and a
PublishBatchcall accepts 10 messages.
In the AWS Management Console
-
Open Amazon SNS, then Topics, Create topic, choose Standard, name it
bookshelf-order-eventsand create it. -
In the queue’s own console page (Amazon SQS,
notifier-queue), open the SNS subscriptions tab and choose Subscribe to Amazon SNS topic, selectbookshelf-order-events, and save. The console also adds the access policy. (Alternatively, in SNS open the topic, Create subscription, protocol Amazon SQS, endpoint the queue ARN.) -
Open the subscription, choose Edit, enable Raw message delivery, and under Subscription filter policy paste
{"eventType": ["OrderPlaced"]}with scope Message attributes. -
Back on the topic, choose Publish message, add the message attribute
eventTypeof type String with valueOrderPlaced, a body, and Publish message; then poll the queue to see it arrive.
With the AWS CLI
TOPIC_ARN=$(aws sns create-topic --name bookshelf-order-events --query TopicArn --output text)
QUEUE_ARN=arn:aws:sqs:$AWS_REGION:$ACCOUNT_ID:notifier-queue
# Queue policy: only this topic may send to the queue
cat > queue-policy.json <<JSON
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "AllowOrderEventsTopic",
"Effect": "Allow",
"Principal": { "Service": "sns.amazonaws.com" },
"Action": "sqs:SendMessage",
"Resource": "$QUEUE_ARN",
"Condition": { "ArnEquals": { "aws:SourceArn": "$TOPIC_ARN" } }
}]
}
JSON
aws sqs set-queue-attributes --queue-url "$QUEUE_URL" \
--attributes "Policy=$(jq -c . queue-policy.json | jq -Rs .)"
# Subscribe with raw delivery and a filter policy on the eventType attribute
aws sns subscribe --topic-arn "$TOPIC_ARN" --protocol sqs --notification-endpoint "$QUEUE_ARN" \
--attributes '{"RawMessageDelivery":"true","FilterPolicy":"{\"eventType\":[\"OrderPlaced\"]}"}'
# Publish with a message attribute
aws sns publish --topic-arn "$TOPIC_ARN" \
--message '{"orderId":"o-1001","email":"reader@example.com"}' \
--message-attributes '{"eventType":{"DataType":"String","StringValue":"OrderPlaced"}}'
The set-queue-attributes call replaces the whole queue policy, so merge any existing statements first. If the queue
uses a customer managed KMS key, the key policy must also allow sns.amazonaws.com to use it, or messages are silently
not delivered. References: aws sns create-topic,
aws sns subscribe,
aws sns publish,
Fanout to Amazon SQS queues,
SNS message filtering.
Publishing from Java
package com.example.bookshelf.orders;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.model.MessageAttributeValue;
import software.amazon.awssdk.services.sns.model.PublishRequest;
@Component
public class OrderEvents {
private final SnsClient sns;
private final String topicArn;
public OrderEvents(SnsClient sns, @Value("${bookshelf.topic-arn}") String topicArn) {
this.sns = sns;
this.topicArn = topicArn;
}
public void orderPlaced(String json) {
sns.publish(PublishRequest.builder()
.topicArn(topicArn)
.message(json)
.messageAttributes(Map.of("eventType",
MessageAttributeValue.builder().dataType("String").stringValue("OrderPlaced").build()))
.build());
}
}
SnsClient comes from the Spring Cloud AWS SNS starter or from SnsClient.create(), and uses the default credential
chain; the task or pod role needs sns:Publish on the topic ARN.
Amazon EventBridge
Amazon EventBridge is a serverless event router. It has four parts that are easy to confuse:
| Part | What it does |
|---|---|
Event buses |
Receive events and deliver them to targets. Every account has a default bus that receives events from AWS services; you create custom buses for your own application events and for cross-account sharing |
Pipes |
Connect one source (SQS, Kinesis, DynamoDB Streams, MSK and others) to one target, with optional filtering, enrichment and transformation |
Scheduler |
Runs one-time or recurring invocations of targets at a time or rate |
Archive and replay |
Stores events from a bus so they can be replayed later (Classic buses) |
Event buses: Classic and the Custom Event Bus
EventBridge now offers two kinds of custom bus, and the official guide recommends starting with the newer one for new
applications (checked 2026-10-01). Custom Event Bus - Classic is the long-standing bus: the bus owner writes rules
with event patterns that send matching events to up to five targets each; events are not retained (use an archive to keep
them). The Custom Event Bus keeps every event for a retention period you choose (1 to 365 days), lets each consuming
team or account create its own subscribers (a filter, an optional transformation and exactly one target) on a bus
shared through AWS Resource Access Manager, supports ordered (FIFO) delivery per event group, deduplication at publish time
and a starting position for each subscriber, which gives replay without a separate archive. Both share the events: IAM
namespace and the events.amazonaws.com principal. The default bus, which receives AWS service events, remains a
Classic-style bus.
| Capability | Custom Event Bus - Classic | Custom Event Bus |
|---|---|---|
Routing |
Rules owned by the bus owner, up to five targets per rule |
Subscribers owned by each consumer, one target each |
Retention and replay |
None built in; add an archive and replay from it |
Built-in retention (1 to 365 days) and a per-subscriber starting position |
Ordering |
Not available |
FIFO per event group, per subscriber |
Cross-account |
Bus resource policy or forwarding to a bus in the other account |
Share the bus with AWS RAM; each account attaches its subscribers |
CLI namespace |
|
|
Older guides and tutorials show only the Classic bus and rules (and the former name CloudWatch Events); those still work, and the Lambda page’s rule examples use them. Use Classic when you need the default bus (AWS service events such as EC2 state changes or CloudTrail events) or when you have rules already, and the Custom Event Bus for a new shared application bus.
In the AWS Management Console
-
Open Amazon EventBridge, then Event buses, Create event bus, and choose the bus type (Custom Event Bus for the newer model or Custom Event Bus - Classic), name it
bookshelf, and create it. -
For a Classic bus open Rules, Create rule, pick the
bookshelfbus, write an event pattern for sourcebookshelf.ordersand detail typeOrderPlaced, and choose Amazon SQS queuenotifier-queueas the target; let the console create the execution role. For the Custom Event Bus open the bus, Subscribers, Create subscriber, set the filter and choose the target. -
To test, open the bus and choose Send events, using the same source and detail type.
With the AWS CLI
# Classic bus, rule and SQS target
aws events create-event-bus --name bookshelf
aws events put-rule --event-bus-name bookshelf --name order-placed \
--event-pattern '{"source":["bookshelf.orders"],"detail-type":["OrderPlaced"]}'
aws events put-targets --event-bus-name bookshelf --rule order-placed \
--targets "Id=notifier,Arn=arn:aws:sqs:$AWS_REGION:$ACCOUNT_ID:notifier-queue"
# The queue needs a policy allowing events.amazonaws.com to send, with aws:SourceArn set to the rule ARN
aws events put-events --entries \
'[{"EventBusName":"bookshelf","Source":"bookshelf.orders","DetailType":"OrderPlaced","Detail":"{\"orderId\":\"o-1001\"}"}]'
# Custom Event Bus (new): 30 days of retention and one subscriber delivering to an SQS queue
BUS_ARN=$(aws eventsv2 create-event-bus --name orders \
--storage-configuration RetentionPeriodInDays=30 --query EventBusArn --output text)
aws eventsv2 create-subscriber --name large-orders --event-bus-arn "$BUS_ARN" \
--filter-configuration '{"Filters":[{"Scope":"DATA","Pattern":"{\"detail\":{\"total\":[{\"numeric\":[\">\",500]}]}}"}]}' \
--invoke-configuration "{\"TargetArn\":\"arn:aws:sqs:$AWS_REGION:$ACCOUNT_ID:large-orders\",\"RoleArn\":\"arn:aws:iam::$ACCOUNT_ID:role/EventBusDeliveryRole\"}"
The delivery role must trust events.amazonaws.com and allow sqs:SendMessage on the target (and on the subscriber’s
dead-letter queue, if you configure --on-failure-configuration). A publish response only confirms that the bus accepted
the event; check the target and the bus metrics to confirm delivery. References:
aws events put-rule,
aws events put-targets,
aws events put-events,
aws eventsv2 create-event-bus,
aws eventsv2 create-subscriber,
Custom Event Bus.
EventBridge Pipes
A pipe is the lightest way to move data between two AWS services: you choose a source, an optional filter, an optional
enrichment step (a Lambda function, a Step Functions state machine, an API destination or API Gateway) and a target.
You pay only for events that pass the filter. A typical Bookshelf use is a pipe from the DynamoDB stream of the Orders
table (see DynamoDB) to an event bus, so that every inserted order becomes an
OrderPlaced event without any application code:
aws pipes create-pipe --name orders-stream-to-bus \
--role-arn "arn:aws:iam::$ACCOUNT_ID:role/orders-pipe-role" \
--source "$ORDERS_STREAM_ARN" \
--source-parameters '{"DynamoDBStreamParameters":{"StartingPosition":"LATEST","BatchSize":10},"FilterCriteria":{"Filters":[{"Pattern":"{\"eventName\":[\"INSERT\"]}"}]}}' \
--target "arn:aws:events:$AWS_REGION:$ACCOUNT_ID:event-bus/bookshelf"
The pipe role needs read permissions on the source (dynamodb:DescribeStream, GetRecords, GetShardIterator,
ListStreams) and events:PutEvents on the target, and trusts pipes.amazonaws.com. In the console use EventBridge,
Pipes, Create pipe. References: aws pipes create-pipe,
EventBridge Pipes.
EventBridge Scheduler
Scheduler is the managed way to run something later or repeatedly: one-time schedules, rate and cron expressions, time
zones, flexible time windows, retry policies and a DLQ per schedule, with templated targets for many AWS APIs. It is the
preferred replacement for scheduled rules in new work. The Lambda page shows a schedule that invokes a function; this one
sends a reminder message to the notifier queue every morning through the universal SQS target:
aws scheduler create-schedule --name daily-digest \
--schedule-expression "cron(0 8 * * ? *)" --schedule-expression-timezone "Europe/Madrid" \
--flexible-time-window Mode=OFF \
--target "{\"Arn\":\"arn:aws:scheduler:::aws-sdk:sqs:sendMessage\",\"RoleArn\":\"arn:aws:iam::$ACCOUNT_ID:role/scheduler-send-to-sqs\",\"Input\":\"{\\\"QueueUrl\\\":\\\"$QUEUE_URL\\\",\\\"MessageBody\\\":\\\"{\\\\\\\"type\\\\\\\":\\\\\\\"digest\\\\\\\"}\\\"}\"}"
The role trusts scheduler.amazonaws.com and allows sqs:SendMessage on the queue. For brevity the quoting above is the
awkward part of the shell, not of Scheduler: prefer --target file://target.json in scripts. References:
aws scheduler create-schedule,
EventBridge Scheduler User Guide.
AWS Step Functions
Step Functions runs state machines defined in Amazon States Language: tasks that call AWS services directly (more than 200 integrations, including SQS, SNS, EventBridge, DynamoDB and Lambda), choices, parallel branches, maps, waits, retries and catches. Use it when a flow has several steps whose order, retries or compensation matter, instead of chaining queues and functions by hand. The Lambda page gives a minimal order-flow definition and compares Step Functions with Lambda durable functions; this page only covers where it sits among the messaging services.
| Aspect | Standard workflows | Express workflows |
|---|---|---|
Maximum duration |
One year |
Five minutes |
Execution semantics |
Exactly-once state execution |
At-least-once (asynchronous) or at-most-once (synchronous) |
Pricing model |
Per state transition |
Per execution, duration and memory |
Callbacks and |
Supported |
Not supported |
Use for |
Long-running, auditable, non-idempotent flows (payments, fulfilment) |
High-volume, short, idempotent event processing |
The workflow type cannot be changed after creation. A state can send a message with the optimized SQS integration
(arn:aws:states:::sqs:sendMessage) and can wait for an external system with the callback pattern
(arn:aws:states:::sqs:sendMessage.waitForTaskToken, Standard only). In the console use Step Functions, State machines,
Create state machine; from the CLI, aws stepfunctions create-state-machine. References:
Step Functions Developer Guide,
Choosing workflow type,
aws stepfunctions create-state-machine.
Brokers and streams, briefly
Amazon MQ
Amazon MQ runs managed Apache ActiveMQ Classic and RabbitMQ brokers, so applications written for JMS, AMQP, MQTT, STOMP or OpenWire can move to AWS without code changes. You choose an instance size and a deployment mode (single instance for development, or a multi-Availability-Zone broker for production: active/standby for ActiveMQ and a three-node cluster for RabbitMQ, where quorum queues replicate across Availability Zones). Brokers live in your VPC and are billed by the hour for the broker instance plus storage, which is the main cost difference from the serverless services above. Prefer SQS and SNS for new AWS-native applications; prefer Amazon MQ when the application already depends on a broker’s protocol or features. The RabbitMQ model is documented on this site in RabbitMQ architecture and the AMQP model and RabbitMQ queue types; Spring and JMS usage in Spring Boot RabbitMQ and other Spring messaging options. CLI: aws mq; guide: What is Amazon MQ?.
Amazon MSK
Amazon Managed Streaming for Apache Kafka runs open-source Apache Kafka, so existing clients, Kafka Connect and Kafka Streams applications work unchanged. MSK Provisioned offers Standard brokers and Express brokers (faster scaling and recovery, a managed-storage model); MSK Serverless removes broker sizing; MSK Connect runs Kafka Connect connectors and MSK Replicator replicates between clusters. Clusters are created in your VPC and authenticated with IAM access control, SASL/SCRAM or mutual TLS. Supported versions move quickly: as checked on 2026-10-01 the documentation lists 3.9.x as the recommended version, 4.0.x and 4.1.x for provisioned clusters, and 4.2.x on Express brokers only, while 3.7.x reached end of support on 2026-09-01, so plan upgrades rather than pinning an old version. MSK is also a Lambda event source (see the Lambda page). Kafka itself is covered in depth on this site, starting at Kafka architecture, with producers, consumers, security and Spring Boot Kafka; Kafka versus RabbitMQ helps choose. Guide: Amazon MSK Developer Guide.
Amazon Kinesis
Kinesis Data Streams is AWS’s native partitioned log. A stream is a set of shards; each shard accepts up to 1 MB/s or 1,000 records per second in and serves 2 MB/s out, a record’s data blob is up to 1 MB, and records are routed to shards by partition key. Capacity is either on-demand (AWS manages the shards) or provisioned (you set the shard count). Retention is 24 hours by default and up to 365 days at extra charge. Consumers either share the read throughput of a shard or use enhanced fan-out for dedicated throughput. Typical Bookshelf use would be a click stream from the web front end:
aws kinesis create-stream --stream-name bookshelf-clicks \
--stream-mode-details StreamMode=ON_DEMAND
aws kinesis put-record --stream-name bookshelf-clicks --partition-key session-42 \
--data "$(echo '{"page":"/books/1"}' | base64)"
Amazon Data Firehose (formerly Kinesis Data Firehose) is the no-code delivery service from a stream or direct puts to S3, Apache Iceberg tables, OpenSearch, Redshift and HTTP endpoints, with buffering and optional transformation. The former Kinesis Data Analytics is now Managed Service for Apache Flink; its legacy SQL applications were shut down on 2026-01-27. Analytics services around these are introduced in AI, data and analytics overview. References: Kinesis Data Streams concepts, aws kinesis, What is Amazon Data Firehose?.
Security
-
Identity. Producers need
sqs:SendMessageorsns:Publishon specific ARNs, consumerssqs:ReceiveMessage,sqs:DeleteMessageandsqs:GetQueueAttributes; grant them to task, function or pod roles (see Identity and access). Use resource policies, always with anaws:SourceArnoraws:SourceAccountcondition, when an AWS service (SNS, EventBridge, S3) sends to a queue. -
Encryption. SQS encrypts at rest by default with SQS-owned keys; use a customer managed KMS key when you need key policies or CloudTrail visibility of use, and remember that every service publishing to such a queue needs
kms:GenerateDataKeyandkms:Decrypt. SNS, EventBridge, Kinesis and MSK also support KMS. -
Network. All of these have public endpoints; use interface VPC endpoints (AWS PrivateLink) from private subnets so traffic does not need a NAT gateway (see VPC networking). MSK and Amazon MQ brokers live inside your VPC.
-
Poison messages. A malformed message that always fails will cycle until it reaches the DLQ; make handlers distinguish permanent from transient errors and alarm on the DLQ.
Pricing model
Prices differ by Region and change over time, so use the dated pricing pages Amazon SQS pricing, Amazon SNS pricing, Amazon EventBridge pricing, AWS Step Functions pricing, Amazon MSK pricing, Amazon MQ pricing and Kinesis Data Streams pricing (all checked 2026-10-01), and model your workload in AWS Pricing Calculator. The cost drivers:
| Service | What you pay for |
|---|---|
SQS |
Requests (every send, receive and delete; a 64 KiB chunk of payload counts as one request unit), so long polling and batching of up to 10 messages reduce cost; data transfer out; a monthly free tier; FIFO requests cost more than standard |
SNS |
Publishes, deliveries by protocol (SQS and Lambda deliveries are cheap, SMS and mobile push are not), payload size, and data transfer out |
EventBridge |
Custom and partner events published to a bus, events delivered to API destinations, Pipes events that pass the filter, Scheduler invocations, and archive storage or Custom Event Bus retention; AWS service events on the default bus are free |
Step Functions |
Standard: state transitions. Express: executions, duration and memory |
MSK |
Broker hours, storage, data transfer between Availability Zones for Standard brokers, and provisioned throughput on Express brokers; Serverless and Connect are billed on their own dimensions |
Amazon MQ |
Broker instance hours and storage, plus data transfer |
Kinesis |
On-demand: per GB written and read; provisioned: shard hours and PUT payload units; extended retention and enhanced fan-out cost extra |
The common surprises: a consumer that short-polls an empty queue all day pays for empty receives; a retry storm multiplies request charges; an MSK or Amazon MQ broker costs the same idle as busy; and a Standard Step Functions loop that transitions through many states per item costs far more than the same logic in an Express workflow.
Limits, recent changes and where older material differs
-
SQS maximum message size is 1 MiB (it was 256 KiB until 2025); SNS is still 256 KiB; Kinesis records are up to 1 MB.
-
The EventBridge Custom Event Bus with built-in retention, ordered delivery and subscribers is documented alongside the Classic bus (checked 2026-10-01), and the guide now recommends it for new applications; older tutorials describe only Classic buses, rules and the name CloudWatch Events.
-
Amazon Pinpoint reaches end of support on 2026-10-30; use SES for email and AWS End User Messaging for SMS and push.
-
Kinesis Data Firehose is now Amazon Data Firehose; Kinesis Data Analytics is now Managed Service for Apache Flink.
-
MSK clusters on Apache Kafka 3.7.x reached end of support on 2026-09-01; Kafka 3.9.x is the recommended version.
-
Older guides recommend polling SQS from EC2 fleets scaled by hand; Lambda event source mappings, ECS or EKS with queue-based scaling, and EventBridge Pipes remove most of that code today.
-
Quotas (queue and topic counts, in-flight messages, rules and subscribers per bus) are in the Service Quotas console and the quota pages linked below; several are adjustable.
Clean up
Delete subscriptions and sources before the resources they point to, and remove queues last.
aws pipes delete-pipe --name orders-stream-to-bus
aws scheduler delete-schedule --name daily-digest
aws events remove-targets --event-bus-name bookshelf --rule order-placed --ids notifier
aws events delete-rule --event-bus-name bookshelf --name order-placed
aws events delete-event-bus --name bookshelf
aws eventsv2 delete-subscriber --subscriber-arn "$SUBSCRIBER_ARN"
aws eventsv2 delete-event-bus --event-bus-arn "$BUS_ARN"
aws sns delete-topic --topic-arn "$TOPIC_ARN" # deletes its subscriptions
aws sqs delete-queue --queue-url "$QUEUE_URL"
aws sqs delete-queue --queue-url "$DLQ_URL"
aws kinesis delete-stream --stream-name bookshelf-clicks
Deleting a queue is permanent and discards its messages, and a deleted queue name cannot be reused for 60 seconds.
delete-event-bus for the Custom Event Bus succeeds only after every subscriber on it is deleted or revoked. Delete any
MSK cluster (aws kafka delete-cluster) or Amazon MQ broker (aws mq delete-broker) you created while experimenting, since
they bill by the hour.
Related pages
-
Lambda: Event-Driven and Serverless Apps shows the
notifierLambda consumingnotifier-queue. -
Sending Email with Amazon SES covers sending the confirmation email and routing SES feedback through SNS or EventBridge.
-
Amazon DynamoDB covers the
Orderstable and its stream. -
Choosing a Compute Service helps decide where queue consumers run.
-
Messaging Reference is the section on messaging theory, Kafka and RabbitMQ.
-
Messaging with SmallRye Reactive Messaging covers Quarkus messaging connectors.
-
Azure holds the Azure equivalents.