Runtime EventBus vs Integration Messaging vs Outbox
Purpose
This document clarifies the architectural boundaries, responsibilities, and correct usage of:
- Runtime EventBus
- Integration Messaging
- Outbox
The goal is to avoid responsibility overlap, prevent SRP violations, and provide a clear decision framework for contributors.
This is a normative architecture decision, not a suggestion.
High-Level Comparison
+-------------------+------------------------+----------------------+
| Concern | Runtime EventBus | Integration Messaging|
| | | / Outbox |
+-------------------+------------------------+----------------------+
| Scope | In-process | Cross-process |
| Persistence | No | Yes (Outbox) |
| Delivery Guarantee| No | Yes |
| Retry / DLQ | No | Yes |
| Use Case | Coordination | Integration |
| Latency | Very low | Higher |
| Lifecycle | Application runtime | Background workers |
+-------------------+------------------------+----------------------+
1. Runtime EventBus
Definition
The Runtime EventBus is an in-process coordination mechanism.
It exists to decouple components inside the same running application, enabling:
- Local fan-out
- Agent orchestration
- Tool execution lifecycle hooks
- RAG step coordination
- Observability and tracing propagation
It is not a messaging system.
Core Characteristics
- In-memory
- Non-persistent
- No retry guarantees
- No ordering guarantees across restarts
- No delivery guarantees
- Extremely low latency
What Runtime EventBus MUST do
- Publish and subscribe to runtime signals
- Support async handlers
- Propagate tracing context
- Fail fast
What Runtime EventBus MUST NOT do
- Persist events
- Retry delivery
- Guarantee delivery
- Integrate with brokers
- Replace messaging systems
- Replace Outbox
Example Usage
event_bus.publish(
event_name="agent.step.completed",
payload={
"agent_id": agent_id,
"step": step_name,
"duration_ms": duration,
}
)
Typical Use Cases
- Agent execution steps
- Tool invocation lifecycle
- RAG pipeline coordination
- Internal state transitions
- Observability hooks
2. Integration Messaging
Definition
Integration Messaging is the system responsible for cross-process and cross-service communication.
It is built around message brokers (Kafka, Redis Pub/Sub, Google PubSub, etc.).
This layer is responsible for reliability, retries, DLQs, delayed delivery, and telemetry.
Core Characteristics
- Cross-process
- Broker-backed
- Retry-aware
- DLQ-aware
- Delay-aware
- Observability-rich
- Payload-agnostic
What Integration Messaging MUST do
- Define Producer / Consumer protocols
- Abstract broker-specific behavior
- Handle retries and DLQ
- Support delayed delivery
- Capture lineage and causality
- Ensure telemetry consistency
What Integration Messaging MUST NOT do
- Act as an in-process EventBus
- Manage domain transactions
- Assume transactional consistency
- Implement business logic
Example Usage
producer.publish(
topic="documents.ingested",
message={
"document_id": doc_id,
"tenant_id": tenant_id,
}
)
Typical Use Cases
- Service-to-service communication
- Async background workflows
- Event-driven integrations
- Delayed processing
- External consumers
3. Outbox
Definition
The Outbox is a reliability pattern, not an event system.
It guarantees that side effects (messages, webhooks, integrations) are emitted only after a successful transaction, and at least once.
It decouples transactional state changes from integration effects.
Core Characteristics
- Persistent
- Transaction-bound
- Retry-aware
- Ordering-aware
- Storage-backed
- Broker-agnostic
What Outbox MUST do
- Persist side effects atomically with domain transactions
- Retry failed deliveries
- Enforce ordering when required
- Prevent message loss
- Support DLQ semantics
What Outbox MUST NOT do
- Act as a runtime EventBus
- Replace Integration Messaging
- Know about subscribers
- Contain business logic
Example Usage
@publish_on_success(
event_name="memory.created",
payload_builder=lambda result: {
"memory_id": result.id,
"tenant_id": result.tenant_id,
}
)
async def create_memory(...):
...
4. Relationship Between the Three
Correct Dependency Direction
Domain Logic
|
v
Outbox (Persistence & Reliability)
|
v
Integration Messaging (Broker)
Separately:
Runtime Components
|
v
Runtime EventBus (In-Process)
Forbidden Couplings
The following are explicitly forbidden:
Outbox -> Runtime EventBus
Runtime EventBus -> Outbox
Runtime EventBus -> Messaging Broker
Messaging Broker -> Runtime EventBus
5. Decision Guide
Use Runtime EventBus when:
- Communication is local
- No persistence is required
- Failure can be tolerated
- Low latency is critical
Use Integration Messaging when:
- Communication crosses process boundaries
- Consumers may be offline
- Retry and DLQ are required
- External systems are involved
Use Outbox when:
- Side effects depend on successful transactions
- Message loss is unacceptable
- Ordering matters
- Exactly-once semantics are desired at the domain level
6. Architectural Rule (Non-Negotiable)
Runtime coordination, integration messaging, and transactional reliability are three distinct concerns and MUST remain separate.
Any design that merges these concerns is considered architecturally invalid in Athomic.
Status
- Runtime EventBus: Runtime coordination layer
- Integration Messaging: Integration and transport layer
- Outbox: Transactional reliability layer
All three are intentionally independent.