Audience: application developers and operators who need to know exactly what delivery guarantees EventMesh provides — ACK tracking, retries, the dead-letter queue, and what happens across crashes and restarts.
Every delivery is tracked by the runtime until the subscriber acknowledges it:
DeliveryStateStore, RocksDB by default).POST /events/ack with the deliveryId, or auto-ACK by returning from an SDK handler).Because an unacknowledged event is re-delivered, each event is delivered at least once; subscribers must be idempotent (dedupe on event id, or use LOAD_BALANCE_STICKY-style ordering per key and business-level idempotency keys).
POST /events/ack body {"deliveryId": "..."} → 200 {"status":"acked"} or 404 for an unknown/already-acked id. (The Java SDK long-poll handler auto-ACKs on return; subscribeWithAck(topic, mode, Predicate) ACKs iff the predicate returns true.)Retry policy per delivery (defaults in ReliableDispatcher):
DEFAULT_JITTER_RATIO).DeadLetterStore, meta-backed when clustered) and the delivery retired.Operators inspect and replay the DLQ through the admin plane: GET /admin/dlq/browse?topic=…&max=…, POST /admin/dlq/replay?topic=…&max=… (see Admin API).
On boot the runtime replays the persisted in-flight records (UniRuntime.alignPullOffsetsToAck + ReliableDispatcher.recover()):
The one thing recovery never does is pretend the absent client ACKed: that would convert an unacknowledged delivery into acknowledged progress and skip the event (the bug class fixed by issue #5379).
When several instances run with a meta store, each topic partition is owned by exactly one instance (PARTITION_OWNED_PULL). If ownership moves while a delivery is in flight, the old owner's ACK is fenced: it raises StaleOwnerException, writes nothing, and the broker redelivers to the new owner. Details: Control plane → delivery topology.
| Scenario | Behavior | Visible signal | Recovery |
|---|---|---|---|
| Local disk full (RocksDB offset/state write fails) | write returns false / throws | offsetWriteFailures counter; pendingDeliveries stops dropping | Free disk; deliveries stay in flight and retry |
| Meta unreachable during DLQ record | store throws; dispatcher keeps delivery in flight | WARN logs | Retry succeeds once Meta heals; records are idempotent |
| Push write failure (SSE/WS) | connection pump nacks the dispatcher | re-delivery counter | Event re-dispatched immediately |
| Process kill -9 | WAL + persisted delivery state survive | — | Boot recovery re-dispatches in-flight records |
Full per-store failure behavior: Control plane → state store failure matrix.
| Piece | Location |
|---|---|
| Dispatcher (ACK / retry / DLQ) | eventmesh-runtime/.../delivery/ReliableDispatcher.java |
| Delivery state (RocksDB) | eventmesh-runtime/.../state/RocksDBDeliveryStateStore.java |
| DLQ ledger (meta, clustered) | eventmesh-runtime/.../state/MetaBackedDeadLetterStore.java |
| Offset store | eventmesh-runtime/.../offset/RocksDBOffsetStore.java |
| Push transports (nack on failure) | eventmesh-runtime/.../push/ConnectionPushPump.java |
| Tests | RecoveryRedispatchTest, DeliveryRecoveryTest, CrossStoreFaultInjectionTest, AckTimeoutRedeliveryIntegrationTest |