Backend Development 12 min read

Using Spring Transaction Hooks to Send Kafka Messages After Transaction Commit

This article explains how to leverage Spring's TransactionSynchronizationManager to detect active transactions and register synchronization callbacks so that Kafka messages are sent asynchronously only after a transaction successfully commits, ensuring data consistency without impacting the main business flow.

Top Architect
Top Architect
Top Architect
Using Spring Transaction Hooks to Send Kafka Messages After Transaction Commit

Today the author introduces a practical case of using Spring transaction hook functions to ensure that Kafka messages are sent only after a transaction commits, avoiding impact on the main business logic.

Case Background

In a payment system each account's fund flow must be archived; the requirement is to push a message to Kafka when writing the flow, and a separate archive service consumes the message and writes to a database with write permission only for the archive system.

Solution Design

The team decides to create a second‑party library (a Spring Boot starter) that provides a simple API for sending messages to Kafka. The library must:

Be a Spring Boot starter.

Use the raw Kafka producer API instead of Spring’s KafkaTemplate to avoid conflicts.

Offer an easy‑to‑use API.

Support transaction semantics so that message sending occurs after the surrounding transaction commits.

Implementation – TransactionSynchronizationManager

The core of the solution relies on TransactionSynchronizationManager . The following Java code shows a simplified implementation:

private final ExecutorService executor = Executors.newSingleThreadExecutor();

public void sendLog() {
    // Check if a transaction is active
    if (!TransactionSynchronizationManager.isSynchronizationActive()) {
        // No transaction – send asynchronously
        executor.submit(() -> {
            try {
                // send message to Kafka
            } catch (Exception e) {
                // log error
            }
        });
        return;
    }

    // Transaction active – register a synchronization callback
    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
        @Override
        public void afterCompletion(int status) {
            if (status == TransactionSynchronization.STATUS_COMMITTED) {
                executor.submit(() -> {
                    try {
                        // send message to Kafka
                    } catch (Exception e) {
                        // log error
                    }
                });
            }
        }
    });
}

The method TransactionSynchronizationManager.isSynchronizationActive() checks a thread‑local variable that the transaction manager sets when a transaction begins. By registering a TransactionSynchronizationAdapter , the library receives a callback after the transaction finishes; if the status is STATUS_COMMITTED , the message is sent asynchronously.

Key Points

1. Use asynchronous sending to minimise impact on the main business. 2. Ensure the hook runs after transaction commit to keep data consistency. 3. Keep the logic inside the library and avoid thread switches, otherwise the thread‑local flag will be lost.

Conclusion

Using Spring’s transaction synchronization facilities allows a clean way to attach Kafka‑sending logic to any transactional method without altering business code, providing reliable, non‑blocking message delivery after successful commits.

backendJavatransactionSpringKafkaTransactionSynchronizationManager
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.