← Back to PRs

#10641: fix(gateway): deduplicate heartbeat events across instances

by saurav470 open 2026-02-06 19:57 View on GitHub →
docs channel: telegram gateway stale
Issue #10061 is about duplicate heartbeat handling when multiple gateways run behind a load balancer. What’s wrong With several OpenClaw Gateway instances (e.g. 3 for HA), the same Telegram webhook is delivered to every instance. Each instance treats the update as new and runs the full heartbeat flow (session_status, exec date, cron list, full AI reply). So one logical heartbeat is processed 3 times and burns about 5–10K tokens per duplicate (e.g. 2K × 3 ≈ 6K tokens in the reported logs). Why it happens Deduplication is per process: each instance keeps its own in-memory set of “seen” updates (e.g. by update_id). There is no shared state, so instance 2 and 3 have never seen that update_id and both process it. The report’s “timestamp-based” note is a bit off — the real issue is in-memory, per-instance dedupe, not timestamps differing. Expected vs actual Expected: Only one instance processes a given heartbeat message; the others skip it. Actual: Every instance processes the same message → repeated tool calls and AI runs. Scope Channel: Observed on Telegram; the same pattern would affect any channel where the same webhook is sent to multiple gateways. Environment: e.g. OpenClaw 2026.2.3-1, Node v22.22.0, 3 gateway processes (PIDs 14697, 22466, 45287). The fix we implemented adds cross-instance inbound deduplication via an optional shared claim store (gateway.inboundDedupe with a file-backed dir or memory), so only one instance “claims” and processes each webhook; the others skip and avoid the extra token cost. <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> - Adds an optional cross-instance inbound deduplication mechanism for webhook-driven channels (aimed at Telegram heartbeat updates behind HA load balancers). - Threads an `inboundClaimStore` through gateway → channel manager → Telegram monitor/webhook → Telegram bot middleware. - Introduces `gateway.inboundDedupe` config (memory default; optional file-backed shared directory) and docs describing HA setup. <h3>Confidence Score: 4/5</h3> - This PR is close to safe to merge, with one interface/behavior mismatch that should be fixed to avoid incorrect dedupe TTL semantics. - Core wiring for cross-instance inbound claims is straightforward and limited in scope. The main concern is that the file-backed claim store currently ignores the per-call TTL parameter even though the interface exposes it, which can lead to incorrect claim expiration behavior for any callers that rely on a custom TTL. - src/infra/inbound-claim.ts <!-- greptile_other_comments_section --> <sub>(4/5) You can add custom instructions or style guidelines for the agent [here](https://app.greptile.com/review/github)!</sub> <!-- /greptile_comment -->

Most Similar PRs