End-to-End Event Streaming With Kafka, Spring Boot and AWS SQS/SNS (Production-Ready Code Guide)
Kafka streams it, SNS fans it out, and SQS decouples it — three platforms, one resilient event pipeline wired together with Spring Boot.
Join the DZone community and get the full member experience.
Join For FreeEvent-driven applications often demand high throughput, reliable delivery and flexible fan out messaging. Each platform in our stack plays a distinct role: Apache Kafka provides a distributed high volume event log, Amazon SQS offers durable point to point queues and Amazon SNS enables pub/sub broadcasting to multiple subscribers. Using them together yields a robust pipeline teams commonly use Kafka for streaming, SQS for decoupled processing and SNS for multicasting events. This synergy leverages the strengths of each platform to build scalable, loosely coupled systems.
Architecture Overview
The pipeline involves multiple components working together in sequence. Below is the event flow:
- Producer Service (Spring Boot & Kafka) – A microservice publishes an event message (in JSON format) to an Apache Kafka topic.
- Kafka Broker – The Kafka cluster durably persists the event and makes it available to consumers. Multiple services can consume from the topic in parallel if needed.
- Bridge Service (Kafka to SNS) – A Spring Boot service consumes the Kafka topic and forwards selected events to an AWS SNS topic.
- AWS SNS (Topic) – The Simple Notification Service fans out the event to all its subscribers. In our setup, an SQS queue is subscribed to this SNS topic.
- Consumer Service (SQS) – Another Spring Boot service listens on the AWS SQS queue and processes the incoming event.
This hybrid design uses Kafka’s high throughput stream as the backbone, while AWS SNS/SQS handle distribution and decoupling at the edges. In practice, Kafka consumers (or connectors) often push critical events to SQS for ordered, independent processing or to SNS for real time fan out. By leveraging SNS’s fan out and SQS’s queuing, we gain additional durability and failure isolation the Kafka to SNS-SQS pattern enhances system reliability through AWS managed persistence and simplified failure handling. The result is a resilient, maintainable architecture that combines on-premises or cloud-based streaming with AWS’s managed messaging services.
Kafka Producer Service
First, we build a Spring Boot service to produce events to Kafka. Include the Spring for Apache Kafka library in the project and configure the Kafka broker address. For JSON data, you can send text strings or use a JSON serializer. Below is a REST controller that publishes incoming JSON payloads to a Kafka topic using Spring’s KafkaTemplate:
@RestController
public class EventProducerController {
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
@PostMapping("/publish")
public String publishEvent(@RequestBody String eventJson) {
// send to Kafka topic
kafkaTemplate.send("events-topic", eventJson);
return "Event published";
}
}
In a real application, the producer might validate or transform the payload before sending. Here we directly send the raw JSON string to Kafka for simplicity. Once this endpoint is called (via an HTTP POST), the event message is written to the events topic on the Kafka cluster.
Kafka-to-SNS Bridge Service
Next, we create a service to bridge Kafka and SNS. Add the Spring Cloud AWS SNS integration (e.g. spring-cloud-aws-starter-sns) and configure the target SNS topic’s ARN in application properties (so we can inject it via @Value). The bridge service uses a @KafkaListener to consume messages from the Kafka topic and then publishes them to the SNS topic:
@Component
public class KafkaToSNSBridge {
@Autowired
private NotificationMessagingTemplate snsTemplate;
@Value("${aws.sns.topic-arn}")
private String topicArn;
@KafkaListener(topics = "events-topic", groupId = "bridge-group")
public void forwardEvent(String eventJson) {
// forward Kafka event to SNS
snsTemplate.convertAndSend(topicArn, eventJson);
}
}
With Spring Cloud AWS, the NotificationMessagingTemplate (or SnsTemplate) simplifies publishing to SNS. The bridge listens on events topic (Kafka) and sends each message to the configured SNS topic ARN. We assume AWS credentials and region are set (via Spring Cloud AWS properties), so this code will authenticate and publish to SNS. In practice, you might filter or transform events here, only forwarding certain types to SNS. This Kafka consumer acts as a bridge that pushes important events into AWS services for external notifications.
SQS Consumer Service
Finally, a consumer service will receive the SNS-forwarded events from an SQS queue. Add the Spring Cloud AWS SQS integration (spring-cloud-aws-starter-sqs), and ensure an SQS queue is subscribed to the SNS topic (with raw message delivery enabled so the queue receives the JSON payload directly). Here’s a component that listens for messages on the queue:
@Component
public class SqsEventListener {
@SqsListener("${aws.sqs.queue}")
public void handleEvent(String eventJson) {
// process event (currently just log it)
System.out.println("Processing event: " + eventJson);
// ... perform business logic ...
}
}
When a message arrives in the queue, Spring Cloud AWS automatically invokes this listener with the payload. The JSON can be deserialized into a POJO if the method signature uses a custom type and Jackson is configured. In this example, we simply log the event. Note that the event flowed from the original Kafka producer through SNS into this SQS consumer, without the producer or final consumer needing direct knowledge of each other. This decoupling allows each component to scale and evolve independently.
Production Considerations
To make this integration production-ready, consider these best practices:
- Error Handling & Retries: Implement retry logic in Kafka consumers to handle transient failures. Leverage Kafka dead-letter topics or SQS dead letter queues for messages that repeatedly fail processing.
- Message Idempotency: Events might be delivered more than once (e.g. Kafka at-least-once semantics or SQS redelivery). Design consumers to handle duplicates safely (using unique IDs or de-duplication).
- Monitoring & Tracing: Combine CloudWatch metrics with Kafka logs in one dashboard for unified monitoring of throughput and errors; include correlation IDs in messages to trace events end-to-end.
- Security: Enforce secure access in production. Use IAM roles for AWS credentials (instead of static keys), and restrict Kafka topic access to authorized services.
- Managed Services: Consider managed solutions to reduce ops overhead – e.g. run Kafka on Amazon MSK, or use AWS Lambda / Kafka Connect to bridge Kafka with SQS/SNS without custom code.
- Ordering Guarantees: If message order is critical, use FIFO SNS topics and SQS queues with message group IDs to preserve ordering. Standard SQS queues do not guarantee order.
By following these practices, you can build a resilient, production ready event pipeline that integrates Kafka with AWS’s messaging ecosystem. In summary, the combined Kafka-SNS-SQS stack forms a powerful backbone for scalable, event driven architectures, uniting Kafka’s streaming capabilities with the reliability of SNS and SQS. Thanks to Spring Boot’s integration support, much of this wiring is handled for you requiring minimal boilerplate and allowing you to focus on business logic while the system reliably delivers events end-to-end.
Opinions expressed by DZone contributors are their own.
Comments