Amazon SNS is a managed pub/sub service on AWS. How topics and subscriptions work, how fan-out to SQS, Lambda, HTTP and email fits backends, how SNS pairs with SQS, and how to get that pattern from application code.
Amazon Simple Notification Service (SNS) is AWS's managed pub/sub layer: publishers send a message to a topic, and SNS pushes a copy to every subscription on that topic. It is how backends fan out one domain event to several consumers without each producer knowing who listens.
SNS alone does not give you a durable work queue, which is what SQS provides. A common pattern is SNS in front of one SQS queue per consumer. This guide covers topics, subscriptions, fan-out, how that differs from Amazon SQS, and how Encore (infrastructure from code) provisions the SNS plus SQS setup from Pub/Sub declared in code.
A topic is the named channel. Publishers call Publish (or publish batch) with a payload. SNS then delivers to every confirmed subscription. Subscription protocols for application workloads include Amazon SQS, AWS Lambda, HTTP(S), Amazon Data Firehose and email. Application-to-person delivery also covers SMS and mobile push.
Delivery is push-based. Subscribers do not poll the topic; SNS invokes the endpoint. When the endpoint is an SQS queue, SNS sends a JSON envelope that wraps the original message so the consumer can pull it from the queue on its own schedule. Standard topics deliver at least once with best-effort ordering. FIFO topics add ordering and deduplication within a message group, at lower throughput.
Message filtering lets a subscription receive only messages whose attributes match a filter policy, so one topic can feed several specialized consumers without separate topics for every event type.
SNS and SQS solve different parts of messaging:
Use SNS when several systems must react to the same event. Use SQS when one pool of workers should process each message, with visibility timeouts and dead-letter queues. Use both together when you want fan-out and durable, independently scaled workers: subscribe an SQS queue to the topic for each consumer.
A common backend layout is one SNS topic per domain event (order placed, user signed up) and one SQS queue per downstream service. The receipt service, the analytics pipeline and the CRM sync each get their own queue subscribed to the same topic. A failure or backlog in one queue does not block the others. Each queue can have its own dead-letter queue and scaling policy.
That wiring is where most of the Terraform sits: topic, queues, subscriptions, queue policies that allow SNS to send, IAM for publishers and consumers, and the same set again for staging. Getting those policies wrong is a common source of silent dropped messages.
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. You declare a topic and subscriptions in code, and on AWS Encore creates an SNS topic with an SQS queue and dead-letter queue per subscription, as listed in the AWS infrastructure docs. On GCP the same declarations become GCP Pub/Sub with dead-letter topics.

Run in your terminal to get started locally.
One publish fans out to two subscriptions. On AWS that is one SNS topic and two SQS queues, each with a dead-letter queue:
// order/order.go
package order
import (
"context"
"encore.dev/pubsub"
)
type OrderPlaced struct {
OrderID int64 `json:"order_id"`
Email string `json:"email"`
}
var OrderPlacedTopic = pubsub.NewTopic[*OrderPlaced]("order-placed", pubsub.TopicConfig{
DeliveryGuarantee: pubsub.AtLeastOnce,
})
type PlaceParams struct {
Email string `json:"email"`
}
//encore:api public method=POST path=/orders
func Place(ctx context.Context, p *PlaceParams) error {
_, err := OrderPlacedTopic.Publish(ctx, &OrderPlaced{OrderID: 42, Email: p.Email})
return err
}
The receipt service is one subscriber. A second service can add another NewSubscription on the same topic without changing the publisher:
// receipt/receipt.go
package receipt
import (
"context"
"time"
"encore.app/order"
"encore.dev/pubsub"
"encore.dev/rlog"
)
var _ = pubsub.NewSubscription(order.OrderPlacedTopic, "send-receipt",
pubsub.SubscriptionConfig[*order.OrderPlaced]{
Handler: SendReceipt,
RetryPolicy: &pubsub.RetryPolicy{
MinBackoff: 1 * time.Second,
MaxRetries: 5,
},
},
)
func SendReceipt(ctx context.Context, e *order.OrderPlaced) error {
rlog.Info("sending receipt", "order_id", e.OrderID)
return nil
}
encore run runs the services with an in-memory Pub/Sub, and the local development dashboard traces each message. A handler that returns an error is retried, and after MaxRetries the message goes to that subscription's dead-letter queue, as covered in the Go Pub/Sub docs. The same model exists in TypeScript. Encore provisions an IAM role for the service, so no topic ARNs or queue URLs sit in config. An existing SNS topic can be attached with import an SNS topic.
Encore Pub/Sub is a queue and fan-out system. It does not keep history for replay the way a log such as Kafka does, and it does not target email or SMS endpoints. When an AI coding agent adds a consumer, it writes one more NewSubscription and tests it locally, and the SQS queue and dead-letter queue arrive with the deploy.
Best fit: Go and TypeScript teams who need fan-out between services on AWS or GCP with retries and dead-letter queues, declared next to the code that publishes and consumes.
sns:Publish from * are a common way staging and production get crossed.Amazon SNS is a fully managed pub/sub service on AWS. Publishers send a message to a topic, and SNS delivers a copy to each subscription. Backends use it to fan out one event to several consumers, and for alerts, email, SMS and mobile push.
SNS is push-based pub/sub: one publish reaches every subscription on the topic. SQS is a pull-based queue: consumers poll a queue and delete messages after processing. For application workers that need buffering and retries, the usual pattern is an SNS topic with one SQS queue subscribed per consumer.
Fan-out is publishing once to a topic so SNS delivers the same message to many endpoints in parallel, such as several SQS queues, Lambda functions or HTTP endpoints. Each subscriber processes independently at its own pace.
With Encore, declare a topic with pubsub.NewTopic and one pubsub.NewSubscription per consumer. Messages are delivered locally during development, and on AWS Encore provisions an SNS topic with an SQS queue and dead-letter queue for each subscription.
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.