adr.zone

ADR Example: Event-driven order lifecycle and domain events (Outcome-First format)

Example of an ADR for moving cross-service work off synchronous call chains: domain events, idempotency, and observability across async hops. The sample status is Proposed so you can see how a team records intent before full rollout; switch the format to compare the same content across templates.

When this type of decision shows up

  • Synchronous request paths fan out to billing, notifications, and analytics and become a reliability choke point.
  • You are willing to own eventual consistency, duplicate delivery, and end-to-end tracing in exchange for looser coupling.
  • You need to add new subscribers (fraud, projections) without inflating a single “god” service API.

Format

Preview

ADR-0029: Introduce event-driven communication for order lifecycle updates

Status

Proposed

Outcome

Side effects (billing, notifications, analytics) decouple from the main write path, reducing retry storms and release coupling.

Decision

Publish domain events for order lifecycle changes. Consumers react asynchronously. Synchronous calls are allowlisted for paths that must complete in a single user-facing request.

Primary tradeoff

We accept eventual consistency, duplicate delivery, idempotency requirements, and harder end-to-end tracing in exchange for looser coupling.

Why

  • Synchronous calls tie ordering, billing, and notifications
  • Prior billing latency spiked and caused retry storms
  • Adding subscribers currently requires changing the order service

Decision boundaries

Impacted:

  • Cross-boundary side effects (billing, notifications, analytics)
  • Event schema and versioning
  • Observability (correlation IDs must cover async work)

Not impacted:

  • Core order write path (synchronous where user latency demands it)
  • Business rule language/runtime
  • Database schema for order state

Assumptions:

  • Teams accept eventual consistency for non-critical paths
  • Idempotency is achievable per consumer
  • Correlation IDs propagate through async hops

Guardrails:

  • Version events; breaking changes get a new name or a migration window
  • Synchronous paths have a maintained allowlist
  • Pilot on read-side subscribers first before extending to writes
  • Poison message runbook required per topic