ediverse Explore the platform

Spotlight PEPPOL BIS Billing 3.0 The EU e-invoicing mandate is here — France Sept 2026, Belgium Jan 2026, Germany 2025.

Event Notification

"Something just happened — come fetch if you care." The leanest possible event, in exchange for residual synchronous coupling.

Problem

A system publishes changes but does not want to pollute the broker with bulky payloads. Not every consumer cares about every order; some only want to filter and enrich on demand. How to notify without paying the cost of a full snapshot?

Forces

  • Full events weigh KBs or even MBs; Notifications weigh a few hundred bytes.
  • The synchronous consumer ↔ producer coupling re-emerges on the detail fetch.
  • The consumer chooses when to enrich (lazy) rather than storing full state.
  • No self-contained replay: without details, the past cannot be reconstructed.
  • The producer must expose a stable, versioned API for the fetch.

Solution

The event carries a minimum: { id, type, aggregateId, version, occurredAt, source }. The interested consumer decides whether to call GET /orders/{aggregateId} on the producer to fetch state. Size stays constant regardless of entity, enabling fan-out at very large scale. Fowler stresses: Event Notification fits when the consumer doesn't consume everything, and accepts added latency (an extra round-trip).

Structure

Producer
   │ publish (minimal payload, ~200 B)
   ▼
┌────────────────────────────────────────────┐
│ Event: OrderConfirmed                      │
│   id: order-42, version: 7                 │
│   occurredAt: 2026-05-16T10:42:00Z         │
│   source: order-service                    │
└──────────┬─────────────────────────────────┘
           │ Consumer X picks it
           ▼
       Consumer X
           │ GET /orders/42 (HTTP, sync)
           ▼
       Producer API (enrich on demand)

EDI implementation

An EDI hub publishes InvoiceIssued with only the ID, partner and UBL number. A "payment broker" consumer fetches the details only for the subset that flows through it. Conversely, a PEPPOL CTC fiscal consumer needing the full UBL payload is better served by Event-Carried State Transfer. Typical case: MdnReceived with the AS2 ID — an ops supervisor fetches the signed payload for audit only when the MDN reports failure.

Anti-patterns

  • Notification followed by an uncached fetch — the producer absorbs N calls per published event.
  • No idempotency on the GET — a consume retry duplicates the enrichment and the invoice.
  • Notification without version — a consumer cannot detect a newer state has already been fetched.
  • Producer without circuit breaker — massive fan-out brings the enrichment API down.
  • Unversioned fetch API — a breaking change breaks every consumer.

Sources

  • Fowler M. — What do you mean by "Event-Driven"?, 2017. martinfowler.com/articles/201701-event-driven.html
  • Newman S. — Building Microservices, 2nd ed., O'Reilly 2021, ch. 4.
  • Stopford B. — Designing Event-Driven Systems, O'Reilly 2018, ch. 6 "Event Notification".