Asynchronous processing in Spring Boot allows long-running tasks to execute in separate threads without blocking the main application flow. This improves responsiveness and throughput, especially for operations such as sending emails, generating reports, or processing notifications.
Key Points: • @EnableAsync activates Spring's asynchronous method execution capability. • @Async executes methods in a separate thread managed by Spring. • Custom thread pools should be configured for better performance and resource management.
Example: Consider an e-commerce application where an order is placed.
Without Asynchronous Processing:
Place Order ↓ Save Order ↓ Send Email ↓ Generate Invoice ↓ Send Notification ↓ Return Response
User waits until all operations complete.
With Asynchronous Processing:
Place Order ↓ Save Order ↓ Return Response Immediately ↓ Send Email (Background) Generate Invoice (Background) Send Notification (Background)
The user receives a faster response while background tasks continue independently.
Step 1: Enable Asynchronous Processing
Add:
@EnableAsync
Example:
@SpringBootApplication
@EnableAsync
public class Application {
}This enables Spring's asynchronous method execution support.
Step 2: Mark Methods with @Async
Code Example:
@Service
public class EmailService {
@Async
public void sendWelcomeEmail(
String email) {
// Email sending logic
}
}Spring executes this method using a separate thread.
Step 3: Return Results if Required
Asynchronous methods can return:
• void • Future<T> • CompletableFuture<T>
Example:
@Async
public CompletableFuture<String> processReport() {return CompletableFuture.completedFuture(
"Report Generated");
}This allows the caller to track progress or retrieve results later.
Step 4: Configure Custom Thread Pool
Default thread configuration may not be suitable for production workloads.
Example:
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor =
new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(50);
executor.initialize();
return executor;
}Benefits: • Better resource utilization. • Prevents thread exhaustion. • Improves scalability.
Important Limitation:
This will NOT work:
@Service
public class EmailService {
public void registerUser() {
sendEmail();
}
@Async
public void sendEmail() {
}
}Reason: • Spring uses proxies for @Async. • Internal method calls bypass the proxy.
Correct Approach: • Call the @Async method from another Spring-managed bean.
Common Use Cases:
• Email Notifications • SMS Sending • File Processing • Report Generation • Audit Logging • Background Data Synchronization
Real-World Example:
Banking Application:
Customer Transfers Money ↓ Transaction Saved ↓ Response Returned Immediately ↓ SMS Notification Sent Asynchronously Email Receipt Generated Asynchronously
Best Practices:
• Configure custom thread pools. • Avoid long-running CPU-intensive tasks on default executors. • Use CompletableFuture when results are required. • Monitor thread pool usage using Actuator. • Handle exceptions properly in asynchronous methods.
Interview Tip: A concise interview answer is: To enable asynchronous processing in Spring Boot, use @EnableAsync in the configuration class and annotate methods with @Async. Spring executes these methods in separate threads, improving application responsiveness. For production applications, custom ThreadPoolTaskExecutor configurations are recommended, and @Async methods should be invoked from another Spring-managed bean because self-invocation bypasses Spring proxies.