Kinoko's TIL Log

GCP Pub-Sub Message Lifecycle Mental Model

The Point

All core GCP Pub/Sub settings can be mapped to four stages of a message’s lifecycle: how long it lives, how many to pull at once, how long to wait for a response, and what to do on failure.

Explanation

The parameters scattered across the docs look like a lot, but each one guards a specific stage in a message’s journey from publish to final processing (or abandonment). Organizing them by lifecycle stage – instead of memorizing each one individually – lets you instantly locate what any new parameter controls. This mental model also ties together the responsibility boundaries of the three resource layers: Topic, Subscription, and Dead Letter.

Knowledge Sugar

1. Parameters by lifecycle stage

StageKey parameterOne-liner
RetentionMessageRetentionDurationHow long an unacked message stays alive
RetentionTopicRetentionDurationHow long the topic keeps a message after ack (for replay)
Flow ControlMaxOutstandingMessagesMax unacked messages a subscriber can hold
Flow ControlMaxOutstandingBytesSame, but measured in bytes (OR logic with messages)
Flow ControlNumGoroutinesNumber of parallel workers running callbacks
Ack/ExtensionAckDeadlineSeconds to ack before redelivery
Ack/ExtensionMaxExtensionUpper bound on client library auto-extending the deadline
Retry/DLQMaxDeliveryAttemptsMax attempts before moving to DLQ
Retry/DLQMinBackoff / MaxBackoffExponential backoff range for push retry
SemanticsExactlyOnceDeliveryWhether to enable exactly-once (has throughput cost)
SemanticsEnableMessageOrderingPreserve order within the same ordering key

The relationship between the three flow control params: MaxOutstandingMessages is the number of seats in the waiting room, NumGoroutines is the number of exam rooms, and MaxOutstandingBytes is the physical space limit of the waiting room.

2. Topic vs Subscription: two-layer responsibilities

A Topic is a named channel responsible for fan-out: one published message gives each subscription its own complete copy. A Subscription handles load balancing: with N pods underneath, they act as competing consumers where the same message goes to only one pod. Each layer has its own job – the Topic decides “which systems receive this event,” and the Subscription decides “how this system distributes workload internally.”

3. Subscription-to-Topic binding is infrastructure

A Subscription binds to a Topic at creation time. After that, application code only uses client.Subscription("name") to retrieve the existing resource without referencing the topic. This is the same pattern as K8s Pod volumeMounts pointing to a PVC name – the infrastructure layer binds things up front, and the application layer just uses the name. In practice, this step is usually handled by Terraform, not written in application code.

4. Dead Letter Policy isolates poison messages

When a message gets nacked or times out repeatedly up to MaxDeliveryAttempts, the broker stops sending it to the original subscription and forwards it to a dead letter topic. A DLQ topic is just a regular topic that semantically collects “messages that could not be processed.” The core value is separating “cannot process” from “not yet processed,” preventing a single poison message from occupying MaxOutstandingMessages quota and dragging down overall throughput. This is even more critical with EnableMessageOrdering on – messages behind the same ordering key would all be blocked.

#gcp #pub-sub #message-queue #distributed-systems #til

← Back to Main Page