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, register synchronization callbacks, and asynchronously send Kafka messages only after a transaction successfully commits, illustrated with a payment‑system example and complete Java code snippets, while also noting thread‑local considerations and promotional offers.

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

In this article, a senior architect introduces a practical technique for handling Spring transaction hooks, aiming to reliably push payment‑system transaction logs to Kafka without affecting the main business flow.

Case background: A payment system must record each account's fund flow and archive these records by sending messages to Kafka, where a dedicated archiving service consumes them and writes to a protected database.

Proposed solution: Develop a second‑party Spring Boot starter library that sends messages to Kafka directly via the Kafka producer API (avoiding Spring's KafkaTemplate to prevent conflicts), provides a simple API, and supports asynchronous operation with transaction awareness.

Key component – TransactionSynchronizationManager: The library checks TransactionSynchronizationManager.isSynchronizationActive() to determine if a transaction is in progress. If no transaction exists, it immediately submits an async task to send the Kafka message. If a transaction is active, it registers a TransactionSynchronizationAdapter that overrides afterCompletion to send the message only after the transaction commits.

Code example:

private final ExecutorService executor = Executors.newSingleThreadExecutor();

public void sendLog() {
    // Determine if a transaction is active
    if (!TransactionSynchronizationManager.isSynchronizationActive()) {
        // No transaction: send message asynchronously
        executor.submit(() -> {
            try {
                // send message to Kafka
            } catch (Exception e) {
                // log exception, notify developers
            }
        });
        return;
    }
    // Transaction active: register synchronization
    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 exception, notify developers
                    }
                });
            }
        }
    });
}

The isSynchronizationActive method works by checking a thread‑local ThreadLocal<Set<TransactionSynchronization>> that is populated when a transaction starts via TransactionSynchronizationManager.initSynchronization() . The registerSynchronization method simply adds the provided synchronization object to this thread‑local set, enabling Spring to invoke it at appropriate transaction lifecycle stages.

Because the synchronization relies on thread‑local storage, it is crucial to avoid switching threads between the transaction and the hook execution; otherwise, the hook will not be triggered.

Conclusion: By using TransactionSynchronizationManager , developers can safely defer Kafka message sending until after a successful transaction commit, ensuring data consistency while keeping the main business logic unaffected.

After the technical discussion, the article includes several promotional sections encouraging readers to join paid AI/ChatGPT communities, purchase exclusive accounts, and participate in various marketing offers.

transactionSpringKafkaSpringBootTransactionSynchronizationManager
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.