Skip to main content

Event-driven side effects

A business transaction commits state and an outbox row together. After commit, the relay publishes an IntegrationEventEnvelope to a Redis Stream. Consumers in other services record an inbox row and handle it asynchronously.

Why this shape​

  • The user request does not wait for push, email, or another service's projection.
  • A crash after commit cannot lose the fact: the row is still pending.
  • A crash after Redis publish but before the mark causes a redelivery. Consumers dedupe on event_id.

Transport history​

Phase 1 dual-wrote Pub/Sub and Streams (ADR 0002). Phase 2 turned stream consumers on by default (ADR 0003). Phase 3 made auth publish only through the outbox and set runtime transport to STREAMS (ADR 0004). The relay process moved out of auth in ADR 0006. Current default is SHARED_EVENTS_TRANSPORT=STREAMS.

Stream key pattern: splick.streams.<context>.<name>. Group env vars look like SHARED_EVENTS_GROUP_SOCIAL_USER_REGISTERED=social-service.user-registered.