KafkaOperations.send returns a future, so a caller must observe completion or failure instead of treating the method call as delivery evidence.
Spring Kafka producer future: observe broker send completion separately from command success
Return the completion signal
The small publisher returns the future from KafkaOperations.send. Its checked success path verifies the topic, key and reservation passed to the API. Its failure path supplies a failed future and confirms that the caller still sees a failure when joining it. Neither check starts a broker. A completed mock future only proves that the gateway did not discard the signal.
A successful producer completion is narrower than an end-to-end business result. It does not say that a consumer ran, wrote its database, or sent a later notification. The exact broker durability meaning depends on producer acknowledgements and broker configuration. If an HTTP request cannot afford to wait, record the intent in the local transaction and hand delivery to a relay. Do not turn fire-and-forget into an implicit success response.
Keep retries tied to one event identity
A timed-out send may have reached Kafka even when the caller did not observe its result. Reusing the same event ID on a retry lets the consumer reject a duplicate. Generating a fresh ID for every attempt defeats that guard. The event ledger closes that local mutation gap; the relay cut points explain the producer side.
Code boundary
CompletableFuture<SendResult<String, StockReservation>> publish(
StockReservation reservation) {
return operations.send("stock-reservations", reservation.sku(), reservation);
}Verification boundary
The Java 21 / Spring Boot 4 source kit checks publisherUsesSkuAsPartitionKeyAndReturnsSendCompletion and failedSendRemainsFailedForCallerToHandle; the checked gateway returns the future directly.
Cost and limits
Waiting on a future adds broker round-trip latency to the caller. An asynchronous callback needs bounded execution and durable retry ownership if delivery matters. The fixture measures neither broker latency nor acknowledgement durability.
Common Mistakes
- Do not mark a command delivered immediately after calling send.
- Do not lose an exceptional completion in an unobserved future.
- Do not regenerate event identity for an uncertain retry.
Read next
Spring Kafka record keys: preserve per-SKU order without claiming global order, Spring outbox to Kafka: name the crash window between send and relay acknowledgement, Spring transactional outbox: commit a receipt and event row together, Spring @Async futures: make worker failure observable to the caller.
