Acknowledgment Timing in Message Delivery

Acknowledgment timing determines when a message is considered successfully handled by a consumer. Acknowledging before processing can cause loss after a crash, while acknowledging after processing can cause duplicate work if the consumer crashes before the acknowledgment.

In message-based systems, a consumer typically receives a message, performs some processing, and then sends an acknowledgment (ack). The broker uses that acknowledgment to decide whether the message can be removed or considered complete. Exactly what happens depends on the broker and its delivery configuration.

With early acknowledgment, the consumer acknowledges as soon as it receives the message and before the business operation finishes. This reduces the chance of redelivery and can simplify throughput, but a crash after the ack and before processing completes can permanently lose the work from the broker's perspective.

With acknowledgment after processing, the consumer performs the business operation first and acknowledges only after it succeeds. If the consumer crashes before the ack, the broker can redeliver the message. That prevents loss under the usual at-least-once model, but the same message may be processed more than once.

For a Java backend, the important design question is therefore not simply when to call `ack`, but whether the processing operation is safe to repeat. Database transactions, unique constraints, idempotency keys, deduplication, and carefully chosen transaction boundaries can make redelivery safe. Acknowledgment timing alone does not provide exactly-once business effects.

Key points

Interview questions

What happens if a consumer acknowledges a message before processing it and then crashes?

The broker may treat the message as successfully handled because it already received the acknowledgment. If the consumer crashes before completing the business operation, the message may not be delivered again. That creates a message-loss window. The exact behavior depends on the messaging system.

Why does acknowledging after processing commonly lead to duplicate processing?

Suppose the consumer completes the business operation but crashes before sending the acknowledgment. The broker has no confirmation that processing completed, so it may redeliver the message. The replacement attempt can execute the business operation again. This is why at-least-once consumers commonly need idempotent processing.

How would you design a consumer that safely handles redelivered messages?

I would identify the operation with a stable idempotency key or message identifier and make the state change conditional on that identity. A database unique constraint can help prevent the same logical operation from being applied twice. I would acknowledge only after the required durable work succeeds. I would also make failure and retry behavior observable so repeated deliveries can be diagnosed.

Can acknowledgment timing by itself provide exactly-once processing?

No. Acknowledgment timing controls when the broker considers a delivery complete, but it does not atomically coordinate the broker with arbitrary external side effects. A consumer can successfully commit a database transaction and then crash before acknowledging, causing the message to be processed again. Exactly-once business effects therefore require additional mechanisms such as transactional integration where supported, idempotency, deduplication, or an outbox-style design.

What failure window exists when processing a message and acknowledging it are separate operations?

There are two important windows. If acknowledgment happens first, a crash before processing completes can cause loss. If processing happens first, a crash before acknowledgment can cause redelivery and duplicate work. The design should therefore choose the failure mode deliberately and make the resulting business operation safe, usually by combining durable state changes with idempotent retry handling.