Overview
The KaireonAI Domain Event Stream publishes lightweight notifications whenever the platform records an interaction or makes a recommendation. Subscribers (analytics workers, ML feature pipelines, external sinks) can consume these events without polling the OLTP database. This stream is separate from thePOST /api/v1/events ingestion endpoint, which accepts inbound customer behavior events.
Topics
Event envelope
Every event is published as JSON with this shape:Choosing a backend
The publisher backend is selected via theEVENT_PUBLISHER environment variable. Pick the trade-off that fits your operational story — durability, cost, ops weight all vary.
Switch backends without code changes — set
EVENT_PUBLISHER and the per-backend env vars below. Topic names + event payloads stay identical, so subscribers don’t need to be rewritten.
Local dev with Redpanda (free Kafka API)
Redpanda is a Kafka-compatible broker that runs as a single binary, no Zookeeper, no JVM. It is included as an optional Docker Compose profile:Durability — what each backend gives you
redis: none. Consumers must be online when an event fires. If no subscriber is connected to a topic, the event is silently dropped.kafka/redpanda/msk: events are persisted to the broker. Consumers can replay from any offset within the configured retention window (default Kafka retention is 7 days). Multiple consumer groups read independently.eventbridge: durable per-event delivery to subscribed targets. No replay (use SQS DLQ for failures).kinesis: durable shards with 24-hour to 365-day replay window.
Configuration reference
Common
Redis backend (EVENT_PUBLISHER=redis)
Kafka / Redpanda backend (EVENT_PUBLISHER=kafka or redpanda)
MSK backend (EVENT_PUBLISHER=msk)
(Equivalent env-var sets exist for
eventbridge and kinesis — see the platform infrastructure container module for the full list.)
Sample subscriber (ioredis)
Where it’s wired
What happens when a publish fails
Every backend rejects on a failed publish — it logs the transport error and rethrows. Failure tolerance is the caller’s decision, not the transport’s, and the two callers make opposite choices:- Outbox events (
outbox_events, drained by the outbox publisher) are the durable path. A rejection drives the retry/backoff ladder and, oncemaxRetriesis exhausted, moves the event todead_letter_events. Nothing is markedpublishedunless the transport accepted it. - Stream events (
interaction.recorded.v1,decision.made.v1) and the workers’*.completednotifications are best-effort: they are emitted after the durable write has already committed, so a failure is logged and swallowed at the call site. Letting it propagate would fail a job that already succeeded and cause the work to be re-run.
Rejection on publish is about handing the event to the broker. It is separate
from durability once accepted: Redis pub/sub still retains nothing, so a consumer
that is offline still misses events. See the backend table above.