Implementing Event Handling

1. Designing Domain Events

AspectDetail
NamingPast tense: OrderPlaced, PaymentCaptured
ImmutableUse records
Self-containedInclude all data needed by consumers
VersionedSchema evolution

Example: Domain event record

public record OrderPlaced(
    UUID orderId, UUID customerId, Money total, Instant occurredAt) {}

2. Implementing Event Publisher

Example: Spring ApplicationEventPublisher

@Service @RequiredArgsConstructor
public class OrderService {
    private final ApplicationEventPublisher events;
    @Transactional
    public Order place(Cart c) {
        var o = repo.save(Order.from(c));
        events.publishEvent(new OrderPlaced(o.id(), c.customerId(), o.total(), Instant.now()));
        return o;
    }
}

3. Implementing Event Subscriber

Example: @EventListener

@Component
public class OrderEmailListener {
    @TransactionalEventListener(phase = AFTER_COMMIT)
    @Async
    public void on(OrderPlaced e) { mail.sendConfirmation(e.orderId()); }
}

4. Implementing Event Bus

TypeUse
In-processSpring events, Guava EventBus
DistributedKafka, RabbitMQ, NATS
CloudSNS+SQS, EventBridge, Pub/Sub

5. Handling Async Event Processing

ConcernDetail
DecouplingPublisher doesn't wait
Failure isolationSubscriber failure doesn't break publisher
OrderUse partitioning if order matters
BackpressureBounded queues

6. Implementing Event Sourcing

ConceptDetail
Append-only logEvents are source of truth
Aggregate stateReplay events to rebuild
SnapshotPeriodic state checkpoint
ProjectionsRead models from events

7. Implementing Event Replay

Example: Rebuild aggregate

public Order load(UUID id) {
    var order = new Order();
    eventStore.streamFor(id).forEach(order::apply);
    return order;
}

8. Designing Event Schema

FieldDetail
eventIdUUID, deduplication
eventTypeFQN or topic name
versionSchema version
occurredAtUTC timestamp
aggregateIdSource entity ID
dataPayload
metadataCorrelation, causation, actor

9. Implementing Event Versioning

StrategyDetail
Additive onlyNew fields optional
UpcastersTransform v1 → v2 on read
Schema registryAvro/Protobuf with compat checks
Multiple versionsPublish both temporarily

10. Handling Event Ordering

MechanismDetail
Single partition per keyKafka partition key = aggregateId
Sequence numberPer-aggregate monotonic
Vector clockDistributed causal order
Re-order at consumerBuffer and sort by seq

11. Implementing Event Deduplication

ApproachDetail
Inbox tablePersist eventId; skip duplicates
Idempotent handlersNaturally safe to replay
Bloom filterMemory-efficient probabilistic
Kafka exactly-onceTransactional producer + consumer

12. Implementing Event Audit Trail

FieldDetail
published_atProducer timestamp
consumed_atPer-consumer timestamp
handler_statussuccess / failed / dlq
retry_countAttempts before success/DLQ