Chaturmind
LearnDSASystem DesignInterview PrepDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth
  • Java Interview Prep

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Java Interview Prep: 2–5 Years

Revise the Fresher Tier

  • Revise: Core Java Fundamentals (Fresher Tier)
  • Revise: Collections, Threads, Java 8 & Coding (Fresher Tier)
  • Revise: Spring Core, Spring Boot & Spring MVC (Fresher Tier)
  • Revise: Hibernate, SQL, Microservices, Maven & Git (Fresher Tier)

Intermediate Core Java

  • Intermediate OOP & Language Features — Interview Questions
  • Enums, Generics, Pass-by-Value & Imports — Interview Questions
  • Collections Internals & Scenarios — Interview Questions
  • JVM, Memory & Class Loading — Interview Questions
  • Exception Design & Serialization Edge Cases — Interview Questions

Java 8 Deep Dive & Stream Coding

  • Lambdas, Functional Interfaces & Method References — Interview Questions
  • Default Methods, Backward Compatibility & Optional — Interview Questions
  • Stream API Internals (Part 1) — Interview Questions
  • Stream API Internals (Part 2) — Interview Questions
  • Stream Coding Problems (Level 2, Part 1) — Interview Questions
  • Stream Coding Problems (Level 2, Part 2) — Interview Questions

Concurrency & Multithreading

  • Synchronization, Locks & Deadlocks — Interview Questions
  • Executors, ThreadLocal & Concurrent Collections — Interview Questions

Spring Framework In Depth

  • Bean Lifecycle, Contexts & Circular Dependencies — Interview Questions
  • Spring Bean Conflicts, AOP, Batch & Injection Styles — Interview Questions

Spring Boot In Depth & Scenarios

  • Spring Boot Internals & Auto-Configuration — Interview Questions
  • Spring Boot Configuration, Profiles & Secrets — Interview Questions
  • Spring Boot Data, Transactions & Caching — Interview Questions
  • Spring Boot Testing, Error Pages & Deployment — Interview Questions
  • Spring Boot Performance, Scaling & Resilience — Interview Questions
  • Spring Boot Async, Events & Messaging — Interview Questions
  • Spring Boot Security Scenarios — Interview Questions
  • Actuator, AOP, Spring Cloud & Distributed Tracing — Interview Questions
  • External APIs, Files, GraphQL & WebFlux — Interview Questions

Spring Security

  • Spring Security — OAuth2, CORS, CSRF & Access Rules — Interview Questions
  • Spring Security — Passwords, Filter Chain, Sessions & Debugging — Interview Questions

Apache Kafka

  • Kafka Architecture, Topics & ZooKeeper vs KRaft — Interview Questions
  • Kafka Producers, Consumers, Reliability & Streams — Interview Questions
  • Kafka Security, Connect & Core Scenarios — Interview Questions
  • Kafka Production Scenarios — Interview Questions

Git, Maven & Gradle (Level II)

  • Git Workflows, Rebase & Conflict Handling — Interview Questions
  • Git Recovery, Hooks, Tags & Collaboration — Interview Questions
  • Maven Builds, Multi-Module Projects & Dependency Resolution — Interview Questions
  • Maven Profiles, settings.xml, Plugins & Quality Gates — Interview Questions
  • Gradle Fundamentals, Migration & Dependencies — Interview Questions
  • Gradle Performance, Plugins, Testing & Publishing — Interview Questions

Deployment & CI/CD

  • Sessions, CI/CD Pipelines, Rollbacks & Secrets — Interview Questions
  • Migrations, Zero-Downtime Releases, Containers & Monitoring — Interview Questions

JUnit 5 & Mockito

  • JUnit 5 — Interview Questions
  • Mockito Basics — Interview Questions
  • Mockito Advanced & Tricky Questions — Interview Questions
Chaturmind
← Java Interview Prep: 2–5 Years

Revise the Fresher Tier

  • Revise: Core Java Fundamentals (Fresher Tier)
  • Revise: Collections, Threads, Java 8 & Coding (Fresher Tier)
  • Revise: Spring Core, Spring Boot & Spring MVC (Fresher Tier)
  • Revise: Hibernate, SQL, Microservices, Maven & Git (Fresher Tier)

Intermediate Core Java

  • Intermediate OOP & Language Features — Interview Questions
  • Enums, Generics, Pass-by-Value & Imports — Interview Questions
  • Collections Internals & Scenarios — Interview Questions
  • JVM, Memory & Class Loading — Interview Questions
  • Exception Design & Serialization Edge Cases — Interview Questions

Java 8 Deep Dive & Stream Coding

  • Lambdas, Functional Interfaces & Method References — Interview Questions
  • Default Methods, Backward Compatibility & Optional — Interview Questions
  • Stream API Internals (Part 1) — Interview Questions
  • Stream API Internals (Part 2) — Interview Questions
  • Stream Coding Problems (Level 2, Part 1) — Interview Questions
  • Stream Coding Problems (Level 2, Part 2) — Interview Questions

Concurrency & Multithreading

  • Synchronization, Locks & Deadlocks — Interview Questions
  • Executors, ThreadLocal & Concurrent Collections — Interview Questions

Spring Framework In Depth

  • Bean Lifecycle, Contexts & Circular Dependencies — Interview Questions
  • Spring Bean Conflicts, AOP, Batch & Injection Styles — Interview Questions

Spring Boot In Depth & Scenarios

  • Spring Boot Internals & Auto-Configuration — Interview Questions
  • Spring Boot Configuration, Profiles & Secrets — Interview Questions
  • Spring Boot Data, Transactions & Caching — Interview Questions
  • Spring Boot Testing, Error Pages & Deployment — Interview Questions
  • Spring Boot Performance, Scaling & Resilience — Interview Questions
  • Spring Boot Async, Events & Messaging — Interview Questions
  • Spring Boot Security Scenarios — Interview Questions
  • Actuator, AOP, Spring Cloud & Distributed Tracing — Interview Questions
  • External APIs, Files, GraphQL & WebFlux — Interview Questions

Spring Security

  • Spring Security — OAuth2, CORS, CSRF & Access Rules — Interview Questions
  • Spring Security — Passwords, Filter Chain, Sessions & Debugging — Interview Questions

Apache Kafka

  • Kafka Architecture, Topics & ZooKeeper vs KRaft — Interview Questions
  • Kafka Producers, Consumers, Reliability & Streams — Interview Questions
  • Kafka Security, Connect & Core Scenarios — Interview Questions
  • Kafka Production Scenarios — Interview Questions

Git, Maven & Gradle (Level II)

  • Git Workflows, Rebase & Conflict Handling — Interview Questions
  • Git Recovery, Hooks, Tags & Collaboration — Interview Questions
  • Maven Builds, Multi-Module Projects & Dependency Resolution — Interview Questions
  • Maven Profiles, settings.xml, Plugins & Quality Gates — Interview Questions
  • Gradle Fundamentals, Migration & Dependencies — Interview Questions
  • Gradle Performance, Plugins, Testing & Publishing — Interview Questions

Deployment & CI/CD

  • Sessions, CI/CD Pipelines, Rollbacks & Secrets — Interview Questions
  • Migrations, Zero-Downtime Releases, Containers & Monitoring — Interview Questions

JUnit 5 & Mockito

  • JUnit 5 — Interview Questions
  • Mockito Basics — Interview Questions
  • Mockito Advanced & Tricky Questions — Interview Questions
HomeLearnJava Interview PrepJava Interview Prep: 2–5 YearsSpring Boot In Depth & Scenarios
✓ FreeIntermediate· 9 min read

Spring Boot Async, Events & Messaging — Interview Questions

Inter-service communication choices (RestClient, OpenFeign, Kafka/RabbitMQ), @Async and its pitfalls, sending welcome emails reliably (after commit, async, retried), monitoring async tasks, notification queues, event-driven design with application events and brokers, and an IoT ingestion backend.

Published September 25, 2026


How to use this lesson

Async and event questions probe reliability. What happens if the email server is down, if the app crashes after the database commit but before the message is sent, or if a message is delivered twice? Answer with the happy path, then with the failure path. The failure path is what gets you hired.

Q1. How would you handle inter-service communication in Spring Boot microservices?

Short answer: Match the style to the need:

  • Synchronous queries (the answer is needed now): RestClient (Spring 6.1+, the modern blocking client), Spring Cloud OpenFeign (declarative interfaces), or WebClient in reactive apps. For internal high-throughput calls, gRPC. Always with timeouts, retries and circuit breakers, and service discovery or load balancing.
  • Asynchronous events or commands (decoupled workflows): Kafka or RabbitMQ, through Spring for Apache Kafka / Spring AMQP, or Spring Cloud Stream. Use the outbox pattern for reliable publishing, and idempotent consumers.
@HttpExchange("/api/inventory")
interface InventoryClient {                                        // Spring 6 declarative HTTP interface
    @GetExchange("/{sku}") StockLevel stock(@PathVariable String sku);
}

Key points to cover:

  • RestTemplate is in maintenance mode. Prefer RestClient or HTTP interfaces in new code.

Learn it in depth → Inter-Service Communication Choices

Q2. How does Spring Boot handle asynchronous operations?

Short answer: With @EnableAsync and @Async, a method call is intercepted by a proxy, and executed on a TaskExecutor instead of the caller's thread. Boot auto-configures a ThreadPoolTaskExecutor (spring.task.execution.*), or virtual threads when spring.threads.virtual.enabled=true. Methods return void or CompletableFuture<T>.

Key points to cover:

  • Other async tools: CompletableFuture composition, @Scheduled background jobs, Spring MVC async request handling (DeferredResult), and messaging listeners.

Q3. How do you enable and use @Async correctly?

Short answer:

  1. Add @EnableAsync.
  2. Annotate a public method on a Spring bean with @Async.
  3. Call it from another bean, because self-invocation bypasses the proxy.
  4. Configure a bounded executor.
  5. Handle failures: CompletableFuture carries the exceptions, and an AsyncUncaughtExceptionHandler handles void methods.
@Configuration
@EnableAsync
class AsyncConfig implements AsyncConfigurer {
    @Override public Executor getAsyncExecutor() {
        var ex = new ThreadPoolTaskExecutor();
        ex.setCorePoolSize(8); ex.setMaxPoolSize(16); ex.setQueueCapacity(500);
        ex.setThreadNamePrefix("async-");
        ex.setTaskDecorator(new ContextCopyingDecorator());       // propagate MDC / security context
        ex.initialize();
        return ex;
    }
    @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (e, method, params) -> log.error("Async failure in {}", method.getName(), e);
    }
}

Key points to cover:

  • @Async work is lost on crash or redeploy, because it lives only in memory. For work that must happen, use a durable queue.

Q4. After a user registers, you must send a welcome email. How would you implement it?

Short answer: Send it after the registration transaction commits, asynchronously, with retries. That way, a slow or failing mail server never breaks registration, and you never email someone whose registration was rolled back.

@Service
class RegistrationService {
    @Transactional
    public User register(SignupRequest req) {
        User user = users.save(User.from(req));
        events.publishEvent(new UserRegistered(user.getId(), user.getEmail()));   // published inside the transaction
        return user;
    }
}

@Component
class WelcomeEmailListener {
    @Async
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)            // only if the save committed
    @Retryable(retryFor = MailException.class, backoff = @Backoff(delay = 2000, multiplier = 2))
    public void onRegistered(UserRegistered e) {
        mailService.sendWelcome(e.email());                                       // JavaMailSender + a template
    }
}

Key points to cover:

  • Configure spring-boot-starter-mail (spring.mail.*), or use an email provider's API (SES, SendGrid).
  • Use templates (Thymeleaf) for the content.
  • Stronger guarantee: write an outbox row in the same transaction, and have a relay publish it to a queue that a mail worker consumes. That survives crashes between the commit and the send.

Q5. How would you manage and monitor asynchronous tasks, tracking progress and handling failures?

Short answer:

  • In-process tasks (@Async):
    • Return CompletableFuture, and attach handlers (whenComplete, exceptionally).
    • Use a named, bounded ThreadPoolTaskExecutor.
    • Expose executor metrics (Micrometer's executor.active, executor.queued, executor.completed).
    • Log with correlation IDs, propagated through a TaskDecorator.
  • Long-running or important jobs: persist job state in a database table (PENDING/RUNNING/DONE/FAILED, progress, attempts), so it survives restarts and can be queried by users (GET /jobs/{id}). Retry failures with backoff, and alert on stuck or failed jobs.
  • Consider Spring Batch or a workflow engine (Temporal) for multi-step jobs.

Q6. You need to process notifications asynchronously through a message queue. How do you set up the integration?

Short answer (Kafka example; RabbitMQ is analogous with RabbitTemplate and @RabbitListener):

  1. Add spring-kafka, and configure spring.kafka.bootstrap-servers, the serializers and a consumer group.
  2. Produce with KafkaTemplate.send(topic, key, event), keyed by user ID so each user's messages stay in order.
  3. Consume with @KafkaListener, making processing idempotent, because delivery is at least once.
  4. Configure error handling: DefaultErrorHandler with backoff, and a dead-letter topic for poison messages.
  5. Monitor consumer lag.
@Service
class NotificationPublisher {
    private final KafkaTemplate<String, NotificationEvent> kafka;
    void publish(NotificationEvent e) { kafka.send("notifications", e.userId(), e); }
}

@Component
class NotificationConsumer {
    @KafkaListener(topics = "notifications", groupId = "notification-service")
    void handle(NotificationEvent e) {
        if (processed.alreadyHandled(e.id())) return;             // idempotency
        channelRouter.deliver(e);
        processed.markHandled(e.id());
    }
}

@Bean
DefaultErrorHandler errorHandler(KafkaTemplate<Object, Object> template) {
    return new DefaultErrorHandler(new DeadLetterPublishingRecoverer(template), new ExponentialBackOff(1000, 2));
}

Common trap: inventing annotations such as @EnableMessaging, or calling convertAndSend on KafkaTemplate. Kafka uses send. convertAndSend belongs to RabbitTemplate and JmsTemplate.

Learn it in depth → Messaging Technology Choices

Q7. How can Spring Boot be used to build an event-driven architecture?

Short answer: At two levels:

  • Inside one service: application events. Publish with ApplicationEventPublisher.publishEvent(anyObject) (since Spring 4.2, events don't need to extend ApplicationEvent), and handle them with @EventListener, or @TransactionalEventListener (tied to commit or rollback). Add @Async for non-blocking listeners. Modules stay decoupled.
  • Across services: domain events on a broker (Kafka or RabbitMQ), through Spring for Apache Kafka or Spring Cloud Stream, with the outbox pattern so events are published if and only if the transaction commits. Consumers are idempotent, and track versions or offsets.

Key points to cover:

  • Spring Modulith can externalise selected application events to a broker, and keeps an event publication registry, so in-process events aren't lost.

Learn it in depth → Event-Driven Architecture Patterns

Q8. Scenario: design a Spring Boot backend that processes real-time streams from thousands of IoT devices.

Short answer:

  • Ingest: devices send data over MQTT (to a broker such as EMQX or HiveMQ, or AWS IoT Core) or HTTP. A bridge pushes the readings into Kafka, partitioned by device ID, so each device's readings stay in order.
  • Process: stateless Spring Boot consumers validate and enrich the readings. Kafka Streams (or Flink) handles windowed aggregations (per-minute averages) and threshold alerts.
  • Store: raw time series in a time-series database (TimescaleDB, InfluxDB) or Cassandra, with time-bucketed partitions. Aggregates go to a queryable store. Cold data is archived to object storage.
  • Serve: dashboards query the aggregates. Alerts go out through a notification service.
  • Operate: autoscale consumers on consumer lag. Apply back-pressure and rate limiting per device. Put invalid messages on dead-letter topics. Authenticate devices (mTLS or tokens).

Learn it in depth → Real-Time Analytics Dashboard

Q9. How would you use application events to notify different parts of your application?

Short answer:

  1. Define event records that describe facts (OrderPlaced, PaymentFailed).
  2. Publish them where the fact happens.
  3. Let each interested module listen, without the publisher knowing who consumes the event.

That removes direct dependencies (and circular ones) between modules.

public record OrderPlaced(long orderId, long customerId, BigDecimal total) { }

@Service
class OrderService {
    private final ApplicationEventPublisher events;
    @Transactional public Order place(Cart cart) {
        Order o = orders.save(Order.from(cart));
        events.publishEvent(new OrderPlaced(o.getId(), o.getCustomerId(), o.getTotal()));
        return o;
    }
}

@Component class LoyaltyListener {
    @TransactionalEventListener void award(OrderPlaced e) { loyalty.addPoints(e.customerId(), e.total()); }
}
@Component class AnalyticsListener {
    @Async @EventListener void track(OrderPlaced e) { analytics.record(e); }
}

Key points to cover:

  • Synchronous @EventListeners run in the publisher's thread and transaction. An exception in a listener fails the publisher. Use @TransactionalEventListener(AFTER_COMMIT) plus @Async for side effects that must not affect the main flow.
  • In-process events are lost on a crash, so use a broker or the outbox pattern for critical ones.

Follow-up questions this topic invites — and their answers

Q: What's the difference between @EventListener and @TransactionalEventListener? A: @EventListener runs immediately when the event is published. @TransactionalEventListener is deferred to a transaction phase (by default AFTER_COMMIT), so it never acts on changes that are later rolled back. It doesn't run at all if there's no transaction, unless fallbackExecution = true.

Q: How do you guarantee exactly-once processing with Kafka in Spring? A: End to end, within Kafka (consume → process → produce), use transactions and idempotent producers. When side effects touch external systems, rely on idempotent consumers (deduplicating by event ID) instead, because exactly-once can't extend to arbitrary external systems.

Q: Why do @Async methods lose the security context or MDC? A: They run on another thread, and both are ThreadLocal-based. Use a TaskDecorator (or DelegatingSecurityContextAsyncTaskExecutor) to copy the context onto the task's thread.

Q: Kafka or RabbitMQ for notifications? A: RabbitMQ suits task queues with per-message routing, priorities and simple work distribution. Kafka suits high-volume event streams that multiple consumers replay independently, and it keeps history. Both work for notifications. Choose based on the throughput you need, how important replay is, and what your team already operates.

Previous

Spring Boot Performance, Scaling & Resilience — Interview Questions

Next

Spring Boot Security Scenarios — Interview Questions

AI Tutor

Lesson: Spring Boot Async, Events & Messaging — Interview Questions

Quick actions

AI responses can be inaccurate. Verify critical information.