In a messaging system, some messages are simply bad. A message may carry data your code cannot parse, point at a record that no longer exists, or trigger a bug in your handler. If Pub/Sub keeps redelivering a message like that, your subscriber keeps failing on it, wasting effort and filling your logs, and sometimes holding up work behind it.
Dead lettering is the standard answer. After a message has failed a set number of times, Pub/Sub stops redelivering it to the subscription and forwards it to a separate topic instead, called the dead letter topic. Your main flow keeps moving, and the problem messages wait in one place where you can examine them, find the cause and decide what to do.
The feature is easy to switch on and surprisingly easy to get wrong. The console form takes a minute, but the setup only works if the permissions are right, and nothing warns you when they are not. This guide covers the whole job: how dead lettering works, how to create a subscription with a dead letter topic using the console with every original screenshot kept in place, and with gcloud. We then cover the IAM roles, how to test it, and how to inspect the failed messages, followed by common mistakes and a short FAQ.
Two details are worth knowing. The dead letter topic is configured on the subscription, not on the topic the subscription reads from. And forwarded messages arrive wrapped with extra attributes that identify where they came from, which helps you trace them.
Menu labels move from time to time, so treat the wording below as a guide.
1. Sign in to the Google Cloud console. Open the navigation menu, choose Pub/Sub and then Subscriptions.
2. Click Create subscription.

3. Enter a subscription ID and choose the main topic it should read from.

4. Set the delivery type. The original uses Push, which sends messages to an endpoint you provide.
5. Set the message retention duration and the subscription expiration period.
6. Set the acknowledgement deadline. This is how long your subscriber has to respond before the attempt counts as a failure.

7. Tick Enable dead lettering.
8. Select the dead letter topic. It must be a different topic from the one the subscription reads from.
9. Set the maximum number of delivery attempts. The allowed range is 5 to 100, and the default is 5.

10. Click Create. The subscription appears in the list.

When the console asks to grant permissions to the Pub/Sub service account, accept. If it does not, or if you are unsure, follow the next section.
This is the step most tutorials leave out. Pub/Sub moves messages to the dead letter topic using its own service account, and that account needs two roles:
The service account follows this pattern, where PROJECT_NUMBER is your project number and not the project name:
service-PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com
In gcloud, find your project number, then grant both roles:
PROJECT_NUMBER=$(gcloud projects describe my-project –format=”value(projectNumber)”)
PUBSUB_SA=”service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com”
gcloud pubsub topics add-iam-policy-binding orders-dead-letter –member=”serviceAccount:${PUBSUB_SA}” –role=”roles/pubsub.publisher”
gcloud pubsub subscriptions add-iam-policy-binding orders-sub –member=”serviceAccount:${PUBSUB_SA}” –role=”roles/pubsub.subscriber”
Without these roles, Google says delivery attempts are not counted, so nothing will ever be forwarded.
Create the dead letter topic and a subscription to hold the failed messages:
gcloud pubsub topics create orders-dead-letter
gcloud pubsub subscriptions create orders-dead-letter-sub –topic=orders-dead-letter
Create the main subscription with dead lettering turned on:
gcloud pubsub subscriptions create orders-sub –topic=orders-topic –dead-letter-topic=orders-dead-letter –max-delivery-attempts=5
To add dead lettering to a subscription that already exists, use the update command with the same flags:
gcloud pubsub subscriptions update orders-sub –dead-letter-topic=orders-dead-letter –max-delivery-attempts=5
Then grant the two roles from the previous section.
gcloud pubsub topics publish orders-topic –message=”bad message”
gcloud pubsub subscriptions pull orders-sub –limit=1
gcloud pubsub subscriptions pull orders-dead-letter-sub –auto-ack –limit=1
Expect the test to take a few minutes, since each attempt waits for the acknowledgement deadline. Because Google describes forwarding as best effort, the message may arrive after slightly fewer or more attempts than you set.
Dead lettering keeps bad messages from clogging a healthy system, but only if the topic, the subscription and the permissions are all in place. Set up the second topic, grant both roles, test with a deliberately failing message, and then watch the dead letter queue.