Implementing Event-Driven Patterns

1. Event Notification Pattern

AspectDetail
PayloadMinimal — just IDs ("OrderPlaced: orderId=123")
Consumer ActionCalls back to source for full data if needed
ProsTiny events; producer keeps single source of truth
ConsAdds sync coupling on lookup; producer must stay available

Example: Notification Event

{ "type": "OrderPlaced", "orderId": "ord_123", "occurredAt": "2026-05-15T10:00:00Z" }

2. Event-Carried State Transfer Pattern

AspectDetail
PayloadFull state needed by consumers
Consumer ActionStores local replica; queries locally
ProsConsumer autonomous, fast reads, resilient
ConsLarger events; replicated data; eventual consistency

3. Event Sourcing Pattern

ConceptDetail
Source of TruthAppend-only stream of events; not current state
Current StateDerived by replaying events (or from snapshot)
ProsFull audit, time travel, projections, retro-active queries
ConsSchema evolution complex; learning curve; query needs CQRS
ToolsEventStoreDB, Axon, Kafka + KSQL, AWS DynamoDB Streams

Example: Rebuild State from Events

public class Account {
    private BigDecimal balance = BigDecimal.ZERO;

    public static Account replay(List<Event> events) {
        Account a = new Account();
        events.forEach(a::apply);
        return a;
    }
    private void apply(Event e) {
        switch (e) {
            case Deposited d  -> balance = balance.add(d.amount());
            case Withdrawn w  -> balance = balance.subtract(w.amount());
            default -> {}
        }
    }
}

4. Event Collaboration Pattern

AspectDetail
DefinitionServices collaborate by reacting to each other's events (choreography)
No Central BrainWorkflow emerges from event reactions
ProsLoose coupling, easy to add new reactors
ConsHard to see end-to-end flow; needs strong tracing

5. Event Store Pattern

PropertyDetail
Append-OnlyEvents never updated/deleted
Stream-BasedOne stream per aggregate (e.g., order-123)
Optimistic ConcurrencyAppend with expected version; fail on mismatch
SubscriptionsProjections subscribe to streams to build read models

6. Event Replay Pattern

Use CaseHow
Rebuild Read ModelReset projection offset, replay all events
Bug FixFix projection logic, replay to correct stored view
New ConsumerBootstrap historical state from beginning of log
ForensicsReconstruct state at any past time

7. Event Ordering Pattern

StrategyMechanism
Per-Partition (Kafka)Same key → same partition → ordered
Single ConsumerOne consumer per partition preserves order
Sequence NumbersProducer stamps monotonic seq; consumer reorders/buffers
Vector ClocksFor causal ordering across multiple producers
Warning: Global ordering across all events kills throughput. Choose the smallest ordering scope your business needs (usually per-aggregate).

8. Event Deduplication Pattern

StrategyDetail
Idempotency KeyProducer assigns unique event ID; consumer stores processed IDs
Inbox TableConsumer records each event ID atomically with side-effect
Bloom FilterProbabilistic dedupe for high volume
TTLExpire seen IDs after time window safe to forget

9. Event Streaming Pattern

AspectDetail
StreamContinuous, unbounded sequence of events
ProcessingStateful operators (map, filter, join, window)
ToolsKafka Streams, Apache Flink, ksqlDB, Spark Structured Streaming
Use CasesReal-time analytics, fraud detection, ETL pipelines

Example: Kafka Streams Aggregation

StreamsBuilder b = new StreamsBuilder();
b.stream("orders.placed", Consumed.with(Serdes.String(), orderSerde))
 .groupBy((k, v) -> v.customerId())
 .windowedBy(TimeWindows.ofSizeWithNoGrace(Duration.ofMinutes(5)))
 .count()
 .toStream()
 .to("orders.per-customer-5min");

10. Event-Driven State Machine Pattern

ElementDetail
StatesEnumerated lifecycle (DRAFT, PLACED, PAID, SHIPPED, DELIVERED, CANCELLED)
TransitionsTriggered by events; rejected if illegal
PersistenceState + version stored; or derived from event log
ToolsSpring Statemachine, Akka FSM, AWS Step Functions