Acknowledgements let Pub/Sub know whether a delivered message was processed successfully. If Pub/Sub doesn’t receive an ack, it will assume the message failed and will re-deliver it. Design your subscribers to handle at-least-once delivery semantics.
Message lifecycle and where acknowledgements fit
- A topic is created and publishers send messages to it.
- A subscription is created for the topic; subscribers either pull messages or receive pushed messages from the subscription.
- Pub/Sub delivers a message to the subscriber (push or pull).
- The subscriber must acknowledge the message to signal successful processing.
- If Pub/Sub does not receive an ack before the ack deadline expires, or if the subscriber explicitly nacks the message, the message becomes eligible for redelivery.
Key implementation details
| Concept | Description | Notes / Example |
|---|---|---|
| Ack ID | Unique identifier for a delivered message (pull-mode) | Required when calling acknowledge() or modifyAckDeadline() |
| Ack deadline | Time window for ack (default 10s) | Per-subscription default; adjustable up to 600s |
| ModifyAckDeadline | Extend/shorten per-message lease | Use to prevent premature redelivery while processing |
| Delivery guarantee | Default is at-least-once | Implement idempotency or dedupe logic to handle duplicates |
Acknowledgement types and behaviors
| Type | Behavior | When to use |
|---|---|---|
| Negative acknowledgement (nack) | Subscriber explicitly indicates failure; in pull-mode you can call modifyAckDeadline(..., ack_deadline_seconds=0) or use message.nack() where supported. Pub/Sub will immediately make the message available for redelivery. | Use when processing definitively failed and you want immediate retry. |
| Explicit acknowledgement (ack) | Subscriber signals successful processing by calling acknowledge() or message.ack(). Pub/Sub will not redeliver the message. | Use after processing succeeds. |
| Modify acknowledgement deadline | Extend or shorten the lease on the message using modifyAckDeadline() to avoid premature redelivery while processing continues. | Use for long-running work or when processing time is variable. |
| Auto-acknowledgement | In push subscriptions, any HTTP 2xx response is treated as an ack. Some client libraries provide options to auto-ack when the message callback returns. | Use with caution—auto-ack can cause lost retries if processing fails after ack. |
| Ack deadline expiry | If no ack or modifyAckDeadline() arrives before expiry, the message becomes eligible for redelivery (common source of duplicates). | Avoid by extending the deadline when necessary and by designing idempotent handlers. |

Practical examples (Python client library)
Synchronous pull: explicitly acknowledge messagesNotes on system design and subscriber behavior
- Subscriber processing times vary. For short, predictable tasks, short ack deadlines may suffice. For long-running tasks, extend the ack deadline per message or increase the subscription default.
- At-least-once delivery requires idempotency or deduplication. If your processing can’t be made idempotent, use dedupe strategies (unique message IDs, external dedupe stores, etc.).
- For push endpoints, only return HTTP 2xx when processing actually succeeded. Returning 2xx will stop retries and is treated as an acknowledgement by Pub/Sub.
- Use
modifyAckDeadline()responsibly to avoid holding messages indefinitely and to ensure fair redelivery behavior.
Be careful with auto-ack behavior. If messages are auto-acknowledged before processing completes (or if a push endpoint returns 2xx while processing actually failed), you may lose the ability to retry and risk data loss or missed processing.
Quick exam pointers
- Pub/Sub uses ack IDs and ack deadlines to manage delivery and retries.
- The typical exam concept is “at-least-once delivery”: messages may be delivered more than once unless you implement deduplication or enable exactly-once features where supported.