

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
12345## Context67This instruction file applies to event-driven and messaging code: Kafka producers, Kafka consumers, Spring `@EventListener` / `ApplicationEventPublisher`, AWS SNS/SQS integrations, and Outbox Pattern implementations. Events are the primary integration mechanism between bounded contexts. All events must have a versioned schema registered with the Schema Registry. Consumers must be idempotent and route failures to a Dead-Letter Queue.89---1011## Coding Standards1213- **Event envelope:** Every domain event carries `eventId` (UUID), `eventType`, `aggregateId`, `aggregateType`, `occurredAt` (ISO 8601 UTC), `schemaVersion`, and `payload`14- **Naming convention:** `{domain}.{entity}.{verb}` in past tense — e.g. `orders.order.placed`, `payments.payment.authorised`15- **Schema evolution:** Only additive changes (add nullable fields); never remove or rename fields without a deprecation lifecycle16- **Outbox Pattern:** Publish events via a transactional outbox table — never produce directly inside a `@Transactional` method17- **Idempotent consumer:** Track processed `eventId` values in a deduplication store; skip already-processed events18- **DLQ routing:** After 3 retry attempts, route to `{topic}.dlq` with error metadata headers19- **Manual offset commit:** `enable.auto.commit=false`; commit only after successful processing and DLQ routing20- **No event sourcing without explicit approval:** CQRS/ES adds significant complexity; get ARB sign-off before introducing2122---2324## Preferred Patterns2526### Event Envelope (Java)2728```java29// ✅ CORRECT — structured event envelope30public record DomainEvent<T>(31 UUID eventId,32 String eventType,33 String aggregateId,34 String aggregateType,35 Instant occurredAt,36 int schemaVersion,37 T payload38) {39 public static <T> DomainEvent<T> of(String eventType, String aggregateId,40 String aggregateType, T payload) {41 return new DomainEvent<>(42 UUID.randomUUID(), eventType, aggregateId, aggregateType,43 Instant.now(), 1, payload44 );45 }46}4748// Usage49var event = DomainEvent.of("orders.order.placed", order.getId().toString(), "Order", new OrderPlacedPayload(order));50```5152### Outbox Pattern5354```java55// ✅ CORRECT — write event to outbox table in same transaction as aggregate56@Service57@RequiredArgsConstructor58public class OrderService {5960 private final OrderRepository orderRepo;61 private final OutboxRepository outboxRepo;6263 @Transactional64 public Order placeOrder(PlaceOrderCommand cmd) {65 Order order = Order.create(cmd);66 orderRepo.save(order);6768 OutboxEntry entry = OutboxEntry.from(69 DomainEvent.of("orders.order.placed", order.getId().toString(), "Order",70 new OrderPlacedPayload(order))71 );72 outboxRepo.save(entry); // same transaction — atomically consistent7374 return order;75 }76}7778// ❌ WRONG — publishing directly in @Transactional risks dual-write inconsistency79@Transactional80public Order placeOrder(PlaceOrderCommand cmd) {81 Order order = orderRepo.save(Order.create(cmd));82 kafkaTemplate.send("orders.placed", order.getId().toString(), payload); // may succeed after DB rollback83 return order;84}85```8687### Idempotent Consumer8889```java90// ✅ CORRECT — deduplication via processed event store91@KafkaListener(topics = "orders.order.placed", groupId = "inventory-service")92public void onOrderPlaced(ConsumerRecord<String, OrderPlacedEvent> record) {93 String eventId = record.headers().lastHeader("eventId").toString();9495 if (processedEventStore.exists(eventId)) {96 log.info("Skipping duplicate event: eventId={}", eventId);97 return;98 }99100 try {101 inventoryService.reserveStock(record.value());102 processedEventStore.markProcessed(eventId);103 } catch (RetryableException exc) {104 throw exc; // Spring Kafka retries105 } catch (Exception exc) {106 log.error("Non-retryable failure; routing to DLQ: eventId={}", eventId, exc);107 dlqProducer.send(record.topic() + ".dlq", record.key(), record.value(), _errorHeaders(eventId, exc));108 }109}110```111112### Retry + DLQ Configuration (Spring Kafka)113114```java115// ✅ CORRECT — fixed retry with DLQ after exhaustion116@Bean117public DefaultErrorHandler errorHandler(KafkaTemplate<String, ?> template) {118 var dlqPublisher = new DeadLetterPublishingRecoverer(template,119 (rec, ex) -> new TopicPartition(rec.topic() + ".dlq", rec.partition()));120121 var backOff = new FixedBackOff(2_000L, 3L); // 2s delay, 3 attempts122 return new DefaultErrorHandler(dlqPublisher, backOff);123}124```125126---127128## Anti-Patterns — Do NOT Generate129130```java131// WRONG: direct Kafka produce inside @Transactional [BLOCKER]132@Transactional133public void placeOrder(PlaceOrderCommand cmd) {134 orderRepo.save(order);135 kafkaTemplate.send("orders.placed", payload); // dual-write — can desync136}137138// WRONG: no deduplication — consumer is not idempotent [BLOCKER]139@KafkaListener(topics = "orders.order.placed")140public void handle(OrderPlacedEvent event) {141 inventoryService.reserveStock(event); // runs twice if message replayed142}143144// WRONG: silently swallowing failures [BLOCKER]145try {146 process(record);147} catch (Exception e) {148 log.warn("Failed to process"); // no DLQ, record lost149}150151// WRONG: past-tense violation — event named in present tense [MINOR]152"orders.order.place" // should be "orders.order.placed"153154// WRONG: breaking schema change — removing a field [MAJOR]155// Removing 'currency' field from OrderPlacedPayload — breaks existing consumers156```157158---159160## Dependencies & Versions161162| Technology | Version | Notes |163|-----------|---------|-------|164| spring-kafka | 3.x | `@KafkaListener`, `DefaultErrorHandler`, `DeadLetterPublishingRecoverer` |165| confluent-kafka-java | 7.x | `KafkaProducer` / `KafkaConsumer` with Schema Registry |166| avro | 1.11+ | Schema Registry Avro serialisation; use specific record types |167| resilience4j | 2.x | Circuit breaker for downstream calls triggered by events |168| aws-java-sdk-sqs | 2.x | `SqsAsyncClient`; visibility timeout ≥ max processing time |169| aws-java-sdk-sns | 2.x | Fan-out pattern; `MessageAttributes` for filtering |170171---172173## Test Conventions174175- Integration test consumers with `@EmbeddedKafka` or Testcontainers Kafka container176- Test idempotency: publish the same event twice and assert the downstream effect occurs once177- Test DLQ routing: configure retries to 0 and inject a failing handler; assert message appears in `.dlq` topic178- Test Outbox relay: commit a transaction containing an outbox entry; assert the relay process publishes to Kafka179- Verify event envelope fields: `eventId`, `occurredAt`, `schemaVersion` are populated on every published event180- Use `@MockBean` to isolate consumer logic from downstream service calls in unit tests181
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| doubts-suplab/eeik-bootstrap.clinerules/golden-rules.md · 1 | Cline rules | gitsecuritydo-not | 61/100 | today | |
| doubts-suplab/eeik-bootstrap.clinerules/project.md · 1 | Cline rules | teststylegit | 63/100 | today | |
| doubts-suplab/eeik-bootstrap.cursor/rules/architecture.mdc · 1 | Cursor rules | do-not | 52/100 | today | |
| doubts-suplab/eeik-bootstrap.cursor/rules/capabilities.mdc · 1 | Cursor rules | teststylegit | 58/100 | today | |
| doubts-suplab/eeik-bootstrap.cursor/rules/golden-rules.mdc · 1 | Cursor rules | gitsecuritydo-not | 61/100 | today | |
| doubts-suplab/eeik-bootstrap.cursor/rules/python.mdc · 1 | Cursor rules | lint-formatstyletypesapi+1 | 77/100 | today | |
| doubts-suplab/eeik-bootstrap.cursor/rules/security.mdc · 1 | Cursor rules | security | 39/100 | today | |
| doubts-suplab/eeik-bootstrap.github/copilot-instructions.md · 1 | Copilot instructions | lint-formatstyletesting-strategygit+2 | 54/100 | today | |
| doubts-suplab/eeik-bootstrap.github/instructions/a2a-protocol.instructions.md · 1 | Copilot instructions | styleagent-behaviour | 48/100 | today | |
| doubts-suplab/eeik-bootstrap.github/instructions/ai-governance.instructions.md · 1 | Copilot instructions | stylearchdo-notagent-behaviour | 61/100 | today | |
| doubts-suplab/eeik-bootstrap.github/instructions/angular.instructions.md · 1 | Copilot instructions | teststyletypestesting-strategy+4 | 69/100 | today | |
| doubts-suplab/eeik-bootstrap.github/instructions/architecture-governance.instructions.md · 1 | Copilot instructions | testlint-formatstylegit+4 | 65/100 | today | |
| doubts-suplab/eeik-bootstrap.github/instructions/autogen.instructions.md · 1 | Copilot instructions | typessecurityagent-behaviour | 50/100 | today | |
| doubts-suplab/eeik-bootstrap.github/instructions/aws-architecture.instructions.md · 1 | Copilot instructions | styletypessecurityperformance | 58/100 | today | |
| doubts-suplab/eeik-bootstrap.github/instructions/aws-data-ml-ai.instructions.md · 1 | Copilot instructions | deployment | 54/100 | today | |
| doubts-suplab/eeik-bootstrap.github/instructions/cdk-terraform.instructions.md · 1 | Copilot instructions | teststylearchtypes+2 | 96/100 | today | |
| doubts-suplab/eeik-bootstrap.github/instructions/cicd.instructions.md · 1 | Copilot instructions | stylesecuritydeploymentdo-not+1 | 65/100 | today | |
| doubts-suplab/eeik-bootstrap.github/instructions/containerisation.instructions.md · 1 | Copilot instructions | buildstylesecuritydo-not | 77/100 | today | |
| doubts-suplab/eeik-bootstrap.github/instructions/crewai.instructions.md · 1 | Copilot instructions | styleagent-behaviour | 48/100 | today | |
| doubts-suplab/eeik-bootstrap.github/instructions/data-engineering.instructions.md · 1 | Copilot instructions | teststyletypesgit+5 | 69/100 | today |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| chihebnabil/lovable-boilerplate.github/instructions/global.instructions.md · 65 | Copilot instructions | buildlint-formatstylearch+4 | 100/100 | 14 days ago | |
| louislam/uptime-kuma.github/copilot-instructions.md · 90k | Copilot instructions | setupbuildtestlint-format+9 | 100/100 | 14 days ago | |
| pytorch/pytorch.github/copilot-instructions.md · 102k | Copilot instructions | setupbuildteststyle+5 | 100/100 | 14 days ago | |
| HerringtonDarkholme/megarepo.github/copilot-instructions.md · 17 | Copilot instructions | setupbuildtestlint-format+7 | 100/100 | 14 days ago | |
| bagisto/bagisto.github/copilot-instructions.md · 28k | Copilot instructions | setupbuildteststyle+5 | 97/100 | 14 days ago | |
| hiyouga/LlamaFactory.github/copilot-instructions.md · 74k | Copilot instructions | setupbuildtestlint-format+5 | 97/100 | 13 days ago | |
| JCodesMore/ai-website-cloner-template.github/copilot-instructions.md · 32k | Copilot instructions | buildlint-formatstylearch+3 | 97/100 | 7 days ago | |
| nerolis-lab/nerolis-lab.github/copilot-instructions.md · 32 | Copilot instructions | setupbuildtestlint-format+11 | 96/100 | 14 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/doubts-suplab-eeik-bootstrap-github-instructions-event-driven-instructions)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.