Spring Non-blocking Rest Send and forget
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
In Spring, "send and forget" means firing an HTTP request without waiting for or caring about the response. This is useful for non-critical operations like logging, analytics, notifications, or triggering background jobs. Spring provides several ways to implement this pattern: @Async with RestTemplate, WebClient (reactive), and CompletableFuture.
Why Send and Forget?
Typical use cases where you do not need the response:
- Sending audit logs to a logging service
- Triggering a webhook notification
- Posting analytics events
- Invalidating an external cache
- Notifying a downstream service about a state change
The caller should not block or slow down waiting for these non-critical operations to complete.
Approach 1: @Async with RestTemplate
The simplest approach uses Spring's @Async annotation to run the REST call on a separate thread:
The caller invokes sendNotification() and continues immediately. The HTTP call runs asynchronously on the thread pool.
Approach 2: WebClient (Reactive, Non-blocking)
Spring WebFlux's WebClient is truly non-blocking — it does not tie up a thread while waiting for the response:
The key is calling .subscribe() instead of .block(). The subscribe() callback handles the response (or error) when it eventually arrives, while the calling thread continues.
Approach 3: CompletableFuture
For more control over async execution:
Approach 4: ApplicationEventPublisher
Decouple the send-and-forget from the caller entirely using Spring events:
Comparison of Approaches
| Approach | Thread Model | Requires WebFlux | Error Handling |
@Async + RestTemplate | Thread pool (blocking I/O) | No | In async method |
WebClient + subscribe() | Event loop (non-blocking) | Yes | In subscribe callback |
CompletableFuture | Thread pool (blocking I/O) | No | In runAsync lambda |
ApplicationEventPublisher | Decoupled via events | No | In event listener |
Common Pitfalls
- Lost exceptions: Since the caller does not wait for the result, exceptions are silently lost unless you log them in the async method. Always add error handling inside the fire-and-forget code.
- Thread pool exhaustion:
@AsyncwithRestTemplateuses a thread pool. If the downstream service is slow, all threads can be blocked waiting for responses. ConfiguremaxPoolSizeandqueueCapacityappropriately, and set timeouts onRestTemplate. - Missing @EnableAsync: The
@Asyncannotation does nothing without@EnableAsyncon a configuration class. The method will run synchronously without it. - Self-invocation: Calling an
@Asyncmethod from within the same class bypasses the proxy — the method runs synchronously. Inject the service into another bean or useApplicationEventPublisherinstead. - Transaction context:
@Asyncmethods run in a separate thread with no access to the caller's transaction. If the caller rolls back, the async method has already fired.
Summary
- Use
@Async+RestTemplatefor simple fire-and-forget in servlet-based Spring apps - Use
WebClientwith.subscribe()for truly non-blocking send-and-forget in reactive apps - Always log errors in async methods — exceptions are otherwise silently lost
- Configure thread pool limits and HTTP timeouts to prevent resource exhaustion
- Use
ApplicationEventPublisherto fully decouple the sender from the HTTP call
Related reading
- Spring OAuth redirect_uri not using https
- Spring RestTemplate - how to enable full debugging/logging of requests/responses?
- Spring RestTemplate GET with parameters
- Spring RestTemplate throws exception Broken pipe, while calling different Rest API Synchronously
- Spring reactor executing consumers asynchronously
- Spring Security and Async Authenticated Users mixed up
- Spring 'NOT IN' in method naming does not work as it expected
- Spring nullable annotation generates unknown enum constant warning

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.