6 Spring Event Best Practices from Production Failures
The author shares six critical Spring Event best practices derived from production incidents, covering graceful shutdown requirements, startup event loss prevention, suitability for eventual consistency over strong consistency, reliability through retry mechanisms, and mandatory idempotency for subscribers.
Spring Event implements a publish-subscribe mechanism where custom events are broadcast to listeners registered via ApplicationListener or @EventListener. The following six practices are distilled from real production failures.
1. Implement Graceful Shutdown Before Using Spring Event
When broadcasting, Spring fetches all listener beans from the ApplicationContext. However, during context shutdown, getBean is prohibited and throws
Do not request a bean from a BeanFactory in a destroy method implementation. In a high‑traffic service (millions of daily orders), shutdown coincided with in‑flight requests, causing event publishing to fail.
Best practice: cut all entry traffic (HTTP, MQ, RPC) before closing the Spring context. Detailed analysis: https://juejin.cn/post/7281159113882468371.
2. Prevent Event Loss During Startup
A Kafka consumer started in an init-method began consuming before @EventListener beans were registered, so published events had no subscribers. Spring Boot only opens HTTP traffic after full startup; the same principle applies to RPC and MQ traffic.
Best practice: enable entry traffic in SmartLifecycle or on ContextRefreshedEvent.
3. Strong Consistency Scenarios Are Unsuitable for Pub/Sub
In order placement, inventory deduction and coupon locking must succeed or fail atomically. Spring Event cannot propagate subscriber failures back to the publisher for rollback. Implementing rollback on top of Spring Event becomes overly complex.
4. Eventual Consistency Scenarios Are Ideal for Spring Event
Post‑order actions (release locks, send MQ messages) only need to eventually succeed. Example: fulfillment completion notifies the settlement system; failure triggers retry, no rollback required. Using @EventListener per event type avoids manual observer patterns or extra Kafka consumer groups. Note: many subscribers may increase Kafka consumption latency.
5. Add Reliability Guarantees for Event Processing
Three approaches:
Subscriber self‑retry – Use @Retryable with spring-retry dependency.
@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 100L, multiplier = 2))
public void performSuccess(PerformEvent event) { }<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.4.RELEASE</version>
</dependency>Kafka consumer group retry – Return consumption failure; Kafka retries or routes to a dead‑letter queue.
Fault reporting platform – After max retries, publish to a fault MQ. Platform collects, alerts developers, and provides a retry button that invokes the business system via RPC SPI.
6. Subscribers Must Be Idempotent
Retries re‑execute all subscribers. Since Spring cannot know which succeeded, each subscriber must guarantee idempotency to avoid data inconsistency.
Spring Event vs. Message Queue
Both are pub/sub, but MQ is heavier and suits inter‑service decoupling (order payment, fulfillment). Spring Event is lightweight and fits intra‑application decoupling. They complement each other.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
