How to implement a Kafka consumer in a Spring MVC web app (using Spring Boot)
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
A Spring MVC application can consume Kafka messages without becoming a dedicated stream-processing service. The usual design is to let Spring Boot manage the Kafka listener container, keep the consumer logic in a service layer, and expose the resulting application state through regular MVC controllers.
Add the Right Dependencies and Configuration
At minimum, the application needs Spring Boot web support and Spring for Apache Kafka.
Then configure Kafka in application.yml.
A stable consumer group id matters because offsets are stored per group. If the group id changes unexpectedly, the app may re-read old messages or skip expected behavior.
Keep the Listener Thin
The listener should hand work off to a service instead of embedding all business logic inside the @KafkaListener method.
This example keeps only recent messages in memory. A production application might validate the payload and then write it to a database, cache, or internal domain service.
Expose the Result Through MVC
The web controller should read from the application service, not from Kafka directly. Kafka ingestion is asynchronous. MVC rendering is request-response. Keeping them separate avoids a lot of coupling.
This keeps the controller synchronous and simple even though the underlying data is fed by Kafka.
Configure Concurrency and Failure Handling Intentionally
A basic consumer can run with default settings, but real applications usually need explicit decisions about concurrency, retries, and dead-letter behavior.
Concurrency should match topic partitions and processing cost. Adding consumer threads without enough partitions will not improve throughput.
Test the End-to-End Flow
A consumer that compiles is not yet a working integration. Start Kafka locally, publish a test message, and verify the MVC endpoint reflects the consumed state.
If the page does not update as expected, inspect logs first. Broker address, topic name, deserializer choice, and group id mistakes are far more common than framework bugs.
Common Pitfalls
- Putting business logic directly inside
@KafkaListenermethods makes the consumer harder to test and evolve. - Treating MVC requests as if they should wait for Kafka consumption confuses asynchronous ingestion with synchronous page rendering.
- Changing the consumer group id casually can reset offset behavior in surprising ways.
- Increasing concurrency without enough topic partitions adds complexity without useful throughput.
- Ignoring retry and dead-letter strategy turns transient processing failures into fragile behavior.
Summary
- Use Spring Boot configuration to wire Kafka into a standard Spring MVC application.
- Keep the Kafka listener thin and move domain work into a service layer.
- Let MVC controllers read processed application state rather than talk to Kafka directly.
- Configure concurrency and failure handling based on real workload and partition design.
- Verify the full path with a real topic and an end-to-end test, not just with compilation.
Related reading
- How to implement a microservice Event Driven architecture with Spring Cloud Stream Kafka and Database per service
- How to implement a stateful message listener using Spring Kafka?
- How to implement contract testing when kafka is involved in microservice architecture?
- How to implement FlinkKafkaProducer serializer for Kafka 2.2
- How to implement a tree data-structure in Java?
- How to implement an asynchronous REST request to a controller using Springboot?
- How to Implement Priority Queues in RabbitMQ/pika
- How to implement request-reply (synchronous) messaging paradigm in Kafka?

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.