SQS vs Pub/Sub: A Comprehensive Comparison for 2026
As distributed systems continue to dominate modern application architecture in 2026, message brokers have become the backbone of decoupled, scalable microservices. Two of the most widely adopted managed messaging services are Amazon Simple Queue Service (SQS) and Google Cloud Pub/Sub. While both solve similar problems—reliable asynchronous communication between services—their design philosophies, feature sets, and operational characteristics differ in ways that can significantly impact your architecture. This tutorial provides a deep, practical comparison to help you choose the right tool for your workload.
What Are SQS and Pub/Sub?
Amazon SQS is a fully managed message queuing service that has been a cornerstone of AWS since 2004. It is fundamentally a point-to-point queue: producers send messages to a queue, and consumers pull messages one at a time. Each message is delivered to exactly one consumer and deleted after successful processing. SQS offers two queue types: Standard (at-least-once delivery, best-effort ordering, nearly unlimited throughput) and FIFO (exactly-once processing, strict ordering within message groups, 300 messages per second per group by default).
Google Cloud Pub/Sub is a fully managed, scalable, real-time messaging service designed for both streaming analytics and event-driven architectures. Unlike SQS, Pub/Sub is a publish/subscribe model: publishers send messages to topics, and multiple subscribers receive copies independently. Pub/Sub offers at-least-once delivery and supports ordering through message ordering keys. It also provides exactly-once delivery as a generally available feature in 2026, closing a long-standing gap with SQS FIFO.
Why the Comparison Matters in 2026
The messaging landscape has evolved rapidly. In 2026, teams are building event-driven architectures that must handle billions of events daily, support multi-region failover, integrate with serverless compute, and maintain strict compliance requirements. Choosing the wrong messaging primitive can lead to message loss, duplicate processing, scaling bottlenecks, or unexpected cost overruns. Understanding the nuanced differences between SQS and Pub/Sub is no longer optional—it is an architectural decision with long-term consequences.
Key considerations include delivery semantics, ordering guarantees, fan-out capabilities, integration with serverless platforms (Lambda and Cloud Functions), dead-letter handling, observability, and pricing models. Let's explore each in detail.
Core Architectural Differences
- Communication Pattern: SQS is point-to-point (one producer, one consumer per message). Pub/Sub is pub/sub (one producer, many independent subscribers).
- Consumer Model: SQS uses a pull model where consumers poll the queue. Pub/Sub uses a push model by default, delivering messages to endpoints, but also supports a pull API via the gRPC streaming pull.
- Message Retention: SQS retains messages up to 14 days. Pub/Sub retains messages up to 31 days, giving consumers more time to recover from outages.
- Maximum Message Size: SQS supports 256 KB (with extended client libraries for larger payloads via S3). Pub/Sub supports 10 MB natively, a significant advantage for media-heavy workloads.
- Fan-out: SQS requires SNS for fan-out to multiple queues. Pub/Sub handles fan-out natively through multiple subscriptions on a single topic.
How to Use Amazon SQS
Let's walk through creating an SQS queue, sending messages, and consuming them using the AWS SDK for Python (boto3).
Creating a Standard Queue
import boto3
sqs = boto3.client('sqs', region_name='us-east-1')
response = sqs.create_queue(
QueueName='order-processing-queue',
Attributes={
'VisibilityTimeout': '60',
'MessageRetentionPeriod': '1209600',
'DelaySeconds': '0'
}
)
queue_url = response['QueueUrl']
print(f"Queue created: {queue_url}")
Sending Messages
import json
message_body = json.dumps({
'order_id': 'ORD-2026-001',
'customer_id': 'CUST-789',
'total': 149.99,
'items': ['SKU-100', 'SKU-200']
})
sqs.send_message(
QueueUrl=queue_url,
MessageBody=message_body,
MessageAttributes={
'OrderType': {
'DataType': 'String',
'StringValue': 'PREMIUM'
}
}
)
Consuming and Deleting Messages
while True:
messages = sqs.receive_message(
QueueUrl=queue_url,
MaxNumberOfMessages=10,
WaitTimeSeconds=20,
MessageAttributeNames=['All']
)
for msg in messages.get('Messages', []):
try:
order = json.loads(msg['Body'])
process_order(order)
sqs.delete_message(
QueueUrl=queue_url,
ReceiptHandle=msg['ReceiptHandle']
)
except Exception as e:
print(f"Processing failed: {e}")
# Message will become visible again after visibility timeout
Creating a FIFO Queue with Message Groups
fifo_response = sqs.create_queue(
QueueName='order-processing-queue.fifo',
Attributes={
'FifoQueue': 'true',
'ContentBasedDeduplication': 'true',
'VisibilityTimeout': '60'
}
)
fifo_url = fifo_response['QueueUrl']
sqs.send_message(
QueueUrl=fifo_url,
MessageBody=json.dumps({'order_id': 'ORD-2026-002'}),
MessageGroupId='CUSTOMER-789',
MessageDeduplicationId='ORD-2026-002'
)
How to Use Google Cloud Pub/Sub
Now let's implement the same workflow using the Google Cloud Pub/Sub Python client library.
Creating a Topic and Subscription
from google.cloud import pubsub_v1
publisher = pubsub_v1.PublisherClient()
subscriber = pubsub_v1.SubscriberClient()
project_id = 'my-gcp-project-2026'
topic_path = publisher.topic_path(project_id, 'order-processing-topic')
subscription_path = subscriber.subscription_path(project_id, 'order-processing-sub')
publisher.create_topic(request={'name': topic_path})
subscriber.create_subscription(
request={
'name': subscription_path,
'topic': topic_path,
'ack_deadline_seconds': 60,
'message_retention_duration': {'seconds': 604800},
'retain_acked_messages': False
}
)
Publishing Messages
import json
order_data = {
'order_id': 'ORD-2026-001',
'customer_id': 'CUST-789',
'total': 149.99,
'items': ['SKU-100', 'SKU-200']
}
future = publisher.publish(
topic_path,
json.dumps(order_data).encode('utf-8'),
order_type='PREMIUM'
)
message_id = future.result()
print(f"Published message ID: {message_id}")
Publishing with Ordering Keys
future = publisher.publish(
topic_path,
json.dumps({'order_id': 'ORD-2026-002'}).encode('utf-8'),
ordering_key='CUSTOMER-789'
)
future.result()
Consuming Messages with a Callback
def callback(message):
try:
order = json.loads(message.data.decode('utf-8'))
process_order(order)
message.ack()
except Exception as e:
print(f"Processing failed: {e}")
message.nack()
streaming_pull = subscriber.subscribe(
subscription_path,
callback=callback,
flow_control=pubsub_v1.types.FlowControl(max_messages=100)
)
import threading
threading.Event().wait()
Dead-Letter Handling
Both services support dead-letter queues (DLQs), but the configuration differs significantly.
SQS Dead-Letter Queue
# Create the DLQ first
dlq = sqs.create_queue(QueueName='order-dlq')
dlq_arn = sqs.get_queue_attributes(
QueueUrl=dlq['QueueUrl'],
AttributeNames=['QueueArn']
)['Attributes']['QueueArn']
# Configure redrive policy on the main queue
import json
redrive_policy = json.dumps({
'deadLetterTargetArn': dlq_arn,
'maxReceiveCount': '5'
})
sqs.set_queue_attributes(
QueueUrl=queue_url,
Attributes={'RedrivePolicy': redrive_policy}
)
Pub/Sub Dead-Letter Topic
from google.cloud import pubsub_v1
from google.cloud.pubsub_v1.types import DeadLetterPolicy
dlq_topic_path = publisher.topic_path(project_id, 'order-dlq-topic')
publisher.create_topic(request={'name': dlq_topic_path})
subscriber.update_subscription(
request={
'subscription': {
'name': subscription_path,
'dead_letter_policy': DeadLetterPolicy(
dead_letter_topic=dlq_topic_path,
max_delivery_attempts=5
)
},
'update_mask': {'paths': ['dead_letter_policy']}
}
)
Serverless Integration
In 2026, serverless integration remains a primary use case. AWS Lambda natively supports SQS as an event source with automatic batching, concurrency controls, and partial batch failure reporting. Google Cloud Functions and Cloud Run integrate with Pub/Sub through push subscriptions or eventarc triggers. A key difference: Lambda's SQS integration uses polling under the hood, while Pub/Sub push delivers messages via HTTP POST to your endpoint, which can reduce latency but requires your service to be publicly or privately reachable.
Lambda Handler for SQS
import json
def lambda_handler(event, context):
for record in event['Records']:
order = json.loads(record['body'])
try:
process_order(order)
except Exception as e:
# With partial batch response enabled, only failed messages retry
raise e
return {'statusCode': 200}
Cloud Function Handler for Pub/Sub
import json
import base64
def process_pubsub_event(event, context):
pubsub_message = base64.b64decode(event['data']).decode('utf-8')
order = json.loads(pubsub_message)
process_order(order)
Performance and Scalability
SQS Standard queues offer virtually unlimited throughput with no configuration. FIFO queues are limited to 300 messages per second per message group, though AWS has introduced high-throughput FIFO mode that can reach thousands of TPS with batching. Pub/Sub scales automatically and can handle millions of messages per second globally. Its push delivery model provides lower end-to-end latency (often under 100ms) compared to SQS short polling, though long polling narrows the gap considerably.
Pricing Comparison
Both services use a pay-per-use model based on requests and data volume. SQS charges per request (a single API call can batch up to 10 messages), with the first one million requests per month free. Pub/Sub charges per message volume (minimum 1 KB per message) with the first 10 GB free per month. For high-volume, small-message workloads, SQS batching often results in lower costs. For large messages or high fan-out scenarios, Pub/Sub's native 10 MB support and multi-subscription model can be more economical.
Best Practices
- Use idempotent consumers: Both services provide at-least-once delivery guarantees. Always design consumers to handle duplicate messages gracefully using deduplication IDs or business-level idempotency keys.
- Batch aggressively: SQS supports batch send, receive, and delete operations (up to 10 messages). Pub/Sub supports batch publishing. Batching dramatically reduces cost and improves throughput.
- Use long polling for SQS: Set
WaitTimeSecondsto 20 to reduce empty responses and lower API costs. - Configure visibility timeouts carefully: Set the timeout longer than your maximum processing time to prevent duplicate processing.
- Always configure DLQs: Poison messages will block progress without a DLQ. Set a reasonable
maxReceiveCount(typically 3 to 5). - Monitor lag and age: Track
ApproximateAgeOfOldestMessagein SQS andoldest_unacked_message_agein Pub/Sub to detect consumer backlogs early. - Use ordering judiciously: Ordering reduces parallelism. Only use FIFO queues or ordering keys when business logic truly requires it.
- Separate concerns with topics: In Pub/Sub, use separate subscriptions per consumer concern rather than filtering everything in one consumer.
- Leverage schema validation: Pub/Sub supports schema registries for Avro and Protobuf. Use them to enforce contract stability across producer and consumer teams.
- Plan for multi-region: SQS queues are regional. For multi-region active-active, consider cross-region replication or Amazon SNS with regional SQS subscribers. Pub/Sub is global by default, simplifying multi-region architectures.
When to Choose Which
Choose SQS when you need simple point-to-point queuing, tight integration with the AWS ecosystem (especially Lambda, Step Functions, and EventBridge), strict per-message ordering with FIFO queues, or fine-grained control over message visibility and consumption pacing. SQS is also ideal when you want a battle-tested, predictable queuing model with minimal operational overhead.
Choose Pub/Sub when you need native fan-out to multiple independent consumers, large message payloads (up to 10 MB), global message routing, integration with BigQuery for streaming analytics, or a push-based delivery model that minimizes consumer-side polling infrastructure. Pub/Sub also excels in event-driven architectures where multiple services react to the same event independently.
Conclusion
Both Amazon SQS and Google Cloud Pub/Sub are mature, production-grade messaging services that can power the most demanding event-driven architectures in 2026. SQS remains the gold standard for simple, reliable point-to-point queuing within AWS, offering predictable semantics and deep ecosystem integration. Pub/Sub shines in scenarios requiring native fan-out, large payloads, global distribution, and tight coupling with analytics pipelines. The right choice depends less on raw feature checklists and more on your cloud strategy, communication patterns, and operational preferences. By understanding the trade-offs in delivery semantics, ordering, scaling, cost, and integration, you can architect messaging systems that are resilient, cost-effective, and ready for the demands of modern distributed applications.