You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SubscribeEvents: support resuming from an event index for reliable at-least-once delivery #245
SubscribeEvents is currently best-effort: events are fanned out over a bounded broadcast channel, so a subscriber that is disconnected, restarting, or too slow misses events with no way to recover them from the stream (the API guide documents this: "A slow subscriber that falls behind will miss events").
For payment-critical consumers this is hard to build on. A daemon driving hodl invoices via Bolt11ReceiveForHash must not miss PaymentClaimable or PaymentSuccessful; accounting and forwarding-analytics consumers need every event exactly because they don't know in advance which payment ids matter, so reconciling via ListPayments/GetPaymentDetails after a gap is either racy or a full rescan.
Proposed API
Two additive proto changes, no new RPC:
messageEventEnvelope {
// Globally monotonic index assigned to every event, across all event kinds.uint64event_index=1;
oneofevent { ... } // unchanged
}
messageSubscribeEventsRequest {
// If set, first replays all events with event_index greater than this// value, in order, then continues with live events on the same stream.// If unset, the stream starts from now (current behavior).optionaluint64resume_after_index=1;
}
Semantics:
One server stream, one ordered sequence: replayed events first, then live events, indistinguishable to the client.
Delivery is at-least-once. The client persists the last processed event_index and, on any disconnect or error, simply resubscribes with it. Duplicate delivery at the seam is allowed; clients dedup by index.
A single global sequence covering all event kinds (payments, forwards, channel state), so one cursor per subscriber is sufficient. Multiple independent subscribers each hold their own cursor; the server keeps no per-subscriber state.
If the server bounds how much history it retains, a defined error for a too-old cursor lets the client detect that it must fall back to a full resync — this contract should be part of the API even though retention itself is an implementation choice.
Relevance to ldk-node
The same API shape would arguably be practical for ldk-node itself.
oh ok you are right @benthecarman
I am checking ldk-node's EventQueue (src/event.rs), and it looks like events don't currently have any stable/persistent index, and once event_handled() is called, the event is popped and discarded — nothing is retained after it's processed. So ldk-server can only re-broadcast events live over an in-memory bounded channel today, with nothing to replay from if a subscriber falls behind or reconnects.
I checked for existing ldk-node issues/PRs covering this and didn't find one that's quite the same (there's one about deduplicating events on restart, and a broader persistence architecture discussion, but neither covers retaining/replaying handled events for external consumers). So it looks like this would need a stable event index plus retaining handled events for a bit so they can be replayed, added upstream in ldk-node first.
I'm still fairly new to this codebase, so wanted to check before opening anything — does that read correct to you, and does it make sense for me to open an issue on ldk-node proposing that, so it can be discussed/implemented there before this one builds on top of it?
Activity
f3r10 commentedon Aug 3, 2026
hi @benthecarman is this issue open to work on?
benthecarman commentedon Aug 3, 2026
@f3r10 this is something we'd need to support in ldk-node first
f3r10 commentedon Aug 4, 2026
oh ok you are right @benthecarman
I am checking ldk-node's EventQueue (src/event.rs), and it looks like events don't currently have any stable/persistent index, and once event_handled() is called, the event is popped and discarded — nothing is retained after it's processed. So ldk-server can only re-broadcast events live over an in-memory bounded channel today, with nothing to replay from if a subscriber falls behind or reconnects.
I checked for existing ldk-node issues/PRs covering this and didn't find one that's quite the same (there's one about deduplicating events on restart, and a broader persistence architecture discussion, but neither covers retaining/replaying handled events for external consumers). So it looks like this would need a stable event index plus retaining handled events for a bit so they can be replayed, added upstream in ldk-node first.
I'm still fairly new to this codebase, so wanted to check before opening anything — does that read correct to you, and does it make sense for me to open an issue on ldk-node proposing that, so it can be discussed/implemented there before this one builds on top of it?
benthecarman commentedon Aug 4, 2026
@f3r10 yeah should open a similiar issue on ldk-node to discuss