Oct 30, 20265 min read

Google Cloud Pub/Sub vs Amazon SQS: Which Message Queue Fits Your Backend

How Google Cloud Pub/Sub and Amazon SQS differ on fan-out, delivery, ordering, message limits and pricing, and how to write queue code that runs on either one.

Google Cloud Pub/Sub and Amazon SQS both move messages between parts of a backend, but they start from different models. Pub/Sub is built around topics, and every subscription gets its own copy of each message. SQS is a queue, where one consumer takes each message, and fan-out comes from putting SNS in front of it.

That difference decides how much infrastructure a simple "order placed, now ship it and email the customer" flow needs. This guide compares the two services on the points that matter for an application backend, and shows how Encore lets you write the flow once and run it on either cloud.

Pub/Sub vs SQS at a glance

EncoreGoogle Cloud Pub/SubAmazon SQS
ModelTopics and subscriptions in codeTopics with independent subscriptionsQueues, SNS for fan-out
DeliveryAt-least-once, retries and dead letters set upPull or push, at-least-once by defaultPull with long polling
OrderingOrdering attribute per topicOrdering keysFIFO queues with message groups
Max message sizeProvider limit10 MB1 MiB
RetentionProvider defaultUp to 31 daysUp to 14 days
Dead lettersCreated for every subscriptionDead-letter topicsDead-letter queues
Local developmentencore run, in-processEmulatorLocalStack or a real queue

Each option is covered below, starting with Encore.

Using one Pub/Sub API on GCP and AWS with Encore

Encore combines an open source infrastructure SDK for TypeScript and Go with a platform that provisions and deploys into your own AWS or GCP account. Pub/Sub is declared in code: a topic with an event type, and subscriptions with handlers. In GCP environments Encore creates Google Cloud Pub/Sub topics and subscriptions with dead-letter topics. In AWS environments the same code becomes SNS topics with SQS queues and dead-letter queues, and Encore provisions an IAM role for each service.

Application code passes through Encore and infrastructure guardrails to resources provisioned in your own AWS or GCP account.
Encore provisions the infrastructure your application needs in your own AWS or GCP account.

Here an orders service publishes an event and a shipping service reacts to it:

// orders/events.go package orders import "encore.dev/pubsub" type OrderPlaced struct { OrderID int64 `json:"order_id"` Email string `json:"email"` } // Google Cloud Pub/Sub on GCP, SNS and SQS on AWS. var Placed = pubsub.NewTopic[*OrderPlaced]("order-placed", pubsub.TopicConfig{ DeliveryGuarantee: pubsub.AtLeastOnce, })
// shipping/shipping.go package shipping import ( "context" "encore.app/orders" "encore.dev/pubsub" "encore.dev/storage/sqldb" ) var db = sqldb.NewDatabase("shipping", sqldb.DatabaseConfig{ Migrations: "./migrations", }) var _ = pubsub.NewSubscription(orders.Placed, "create-shipment", pubsub.SubscriptionConfig[*orders.OrderPlaced]{ Handler: createShipment, }, ) // Delivery is at-least-once, so a redelivered event must not create a second shipment. func createShipment(ctx context.Context, e *orders.OrderPlaced) error { _, err := db.Exec(ctx, ` INSERT INTO shipments (order_id, status) VALUES ($1, 'pending') ON CONFLICT (order_id) DO NOTHING`, e.OrderID) return err }

The migration in shipping/migrations creates the shipments table the queries use:

-- shipping/migrations/1_create_shipments.up.sql CREATE TABLE shipments ( order_id BIGINT PRIMARY KEY, status TEXT NOT NULL );
Get started
brew install encoredev/tap/encore &&
encore app create
Copy

Run in your terminal to get started locally.

A second subscription, say send-receipt in an email service, gets its own copy of every event with its own retries and dead letters. On GCP that is another Pub/Sub subscription, and on AWS another SQS queue subscribed to the SNS topic, with no extra code beyond the handler. encore run delivers events in process and shows each publish and handler call in the local trace view.

An agent adding the receipt email writes one handler and one subscription in Go, and tests it locally.

Google Cloud Pub/Sub: topics with independent subscriptions

Pub/Sub delivers each message published to a topic to every subscription attached to it. Subscribers can pull messages or have Pub/Sub push them to an HTTPS endpoint, which suits Cloud Run. Ordering keys keep messages with the same key in order, dead-letter topics catch messages that keep failing, and exactly-once delivery is available for pull subscriptions.

Per the Pub/Sub quotas, messages can be up to 10 MB and retained for up to 31 days. Pricing is based on the volume of data published and delivered, per Pub/Sub pricing, so many small messages are cheap and large payloads add up.

Amazon SQS: queues with one consumer per message

SQS stores messages until a consumer receives and deletes them. A visibility timeout hides a received message from other consumers while it is processed, and a redrive policy moves it to a dead-letter queue after a set number of failures. Standard queues offer high throughput with occasional duplicates and loose ordering, and FIFO queues give strict ordering per message group with deduplication.

Per the SQS message quotas, messages can be up to 1 MiB and retained for up to 14 days. Pricing is per request, per SQS pricing. For fan-out you add an SNS topic and subscribe one queue per consumer, each with a queue policy allowing SNS to send to it.

Good to know

Both services deliver at least once in their default modes, so handlers should be idempotent no matter which you pick. A unique constraint and ON CONFLICT DO NOTHING, as in the shipping handler above, is usually enough.

How to choose

Pick Encore when you want topics and subscriptions defined next to the code that uses them, with dead letters created for you, and the option to run the same code on Google Cloud Pub/Sub or on SNS and SQS.

Pick Google Cloud Pub/Sub directly when you are on GCP and want push delivery to Cloud Run or messages larger than 1 MiB. Pick SQS directly when you are on AWS and need a simple work queue for one consumer, or FIFO ordering with deduplication.

Frequently asked questions

What is the difference between Google Pub/Sub and Amazon SQS?

Google Cloud Pub/Sub is a topic-based messaging service: publishers send to a topic and every subscription gets its own copy, delivered by pull or push. Amazon SQS is a queue: each message is consumed by one receiver, and fan-out to several consumers needs SNS in front of multiple SQS queues.

Is Google Pub/Sub the same as SNS plus SQS?

Functionally close. A Pub/Sub topic with several subscriptions behaves like an SNS topic fanning out to several SQS queues, each with its own backlog and retries. The differences are in the details: Pub/Sub messages can be up to 10 MB and kept for up to 31 days, while SQS messages are up to 1 MiB and kept for up to 14 days.

How do I write Pub/Sub code that works on both GCP and AWS?

With Encore, you declare a topic with pubsub.NewTopic in Go or new Topic in TypeScript and add subscriptions in code. In a GCP environment Encore creates Google Cloud Pub/Sub topics and subscriptions with dead-letter topics, and in an AWS environment it creates SNS topics with SQS queues and dead-letter queues. Locally, encore run uses an in-process implementation.

Deploy to your cloud on AWS and Google Cloud
without managing infrastructure

Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.

~/orders — claude
Claude Code
Claude Code v2.1.180Opus 5.5~/orders