kafka-patterns
Skill27 starsChanged 9 months agoMITView on GitHub
Spring Kafka producer/consumer patterns, idempotent consumers, dead letter topics, and manual offset commits. Use when producing to or consuming from Kafka topics in a Spring Boot service.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- 14-848-Cloud-Infrastructure/agentic-skillstheir own version, first seen Oct 25, 2026
- Systems-and-Toolchains-for-AI-Engineers/agentic-skillstheir own version, first seen Oct 8, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- 14-848-Cloud-Infrastructure/agentic-skills★ 4same name
- Systems-and-Toolchains-for-AI-Engineers/agentic-skills★ 2same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository14 other files it gives its agents.
- examples/CLAUDE.mdCLAUDE.md
- backend-patternsSkill
- eval-harnessSkill
- frontend-patternsSkill
- iterative-retrievalSkill
- java-coding-standardsSkill
- jpa-patternsSkill
- postgres-patternsSkill
- python-patternsSkill
- python-testingSkill
- security-reviewSkill
- springboot-patternsSkill
- springboot-securitySkill
- springboot-tddSkill
The file
Files
Kafka Patterns (Spring Kafka)
Concrete implementations of the conventions in rules/infra.md: topic naming, manual commits, idempotent consumers, and dead letter topics.
When to Activate
- Adding a
@KafkaListenerconsumer or aKafkaTemplateproducer - Designing a new topic or partition key
- Handling consumer failures without losing or duplicating messages
- Setting up a dead letter topic for a consumer group
Producer
@Service
public class OrderEventProducer {
private final KafkaTemplate<String, OrderCancelledEvent> kafkaTemplate;
public OrderEventProducer(KafkaTemplate<String, OrderCancelledEvent> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
public void publishCancelled(Order order) {
// Partition key = orderId keeps every event for one order in the same
// partition, so a consumer sees them in order.
String topic = "orders.order.cancelled";
OrderCancelledEvent event = OrderCancelledEvent.from(order);
kafkaTemplate.send(topic, order.getId().toString(), event)
.whenComplete((result, ex) -> {
if (ex != null) {
log.error("Failed to publish {} for order {}", topic, order.getId(), ex);
}
});
}
}Consumer with Manual Commit + Idempotency
@Component
public class OrderCancelledConsumer {
private final ProcessedEventRepository processedEvents;
private final InventoryService inventoryService;
public OrderCancelledConsumer(ProcessedEventRepository processedEvents, InventoryService inventoryService) {
this.processedEvents = processedEvents;
this.inventoryService = inventoryService;
}
@KafkaListener(topics = "orders.order.cancelled", groupId = "inventory-service")
public void handle(ConsumerRecord<String, OrderCancelledEvent> record, Acknowledgment ack) {
String eventId = record.key() + ":" + record.offset();
// Idempotency guard: at-least-once delivery means this handler can run
// more than once for the same record. Check-then-insert on a unique
// constraint, not a plain SELECT, to survive concurrent redelivery.
if (processedEvents.existsById(eventId)) {
ack.acknowledge();
return;
}
try {
inventoryService.rollback(record.value().orderId());
processedEvents.save(new ProcessedEvent(eventId, Instant.now()));
ack.acknowledge();
} catch (Exception ex) {
log.error("Failed to process cancellation for order {}", record.value().orderId(), ex);
// Do not acknowledge — the record will be redelivered. A retry
// policy + dead letter topic (below) bounds how many times.
}
}
}# application.yml — manual commit, no auto-commit
spring:
kafka:
consumer:
enable-auto-commit: false
auto-offset-reset: earliest
listener:
ack-mode: manualDead Letter Topic
@Bean
public DefaultErrorHandler errorHandler(KafkaTemplate<Object, Object> kafkaTemplate) {
var recoverer = new DeadLetterPublishingRecoverer(kafkaTemplate,
(record, ex) -> new TopicPartition(record.topic() + ".dlt", record.partition()));
// 3 retries with backoff, then publish to <topic>.dlt instead of blocking
// the partition forever on a poison message.
return new DefaultErrorHandler(recoverer, new FixedBackOff(1000L, 3));
}Topic Naming and Partition Keys
| Concern | Convention | Example |
| Topic name | <domain>.<entity>.<event> | orders.order.cancelled |
| Partition key | Field that must preserve order | orderId, userId |
| Consumer group | One per logical consumer | inventory-service, notification-service |
| Dead letter topic | <topic>.dlt | orders.order.cancelled.dlt |
Anti-Patterns
- Auto-commit with business logic in the listener — a crash between poll and processing silently drops the message. Use manual
Acknowledgment. - No idempotency check — Kafka is at-least-once; the same record WILL be redelivered after a rebalance or retry. Every consumer must tolerate duplicates.
- JSON without a schema — fine for prototyping, but breaks silently on producer/consumer version drift in production. Prefer Avro/Protobuf with Schema Registry per
rules/infra.md. - One giant topic for every event type — makes consumer group scaling and retention policy impossible to tune per event. Split by domain/entity.
Related
- Rule:
infra.md— Kafka/Flink conventions this skill implements - Rule:
java-springboot.md—@KafkaListener/KafkaTemplateusage
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

