Overview
By default, every inbound history-sync notification from the phone is accepted and enters the major-sync queue for download, decompression, and dispatch asEvent::HistorySync. That matches WhatsApp Web’s behavior and is the right choice for a client that needs history.
A bot that only cares about a subset of syncs — or that wants to skip peer-data-request chunks, cap per-chunk size, or drop everything past initial pairing — can register a HistorySyncAdmission policy. The policy runs synchronously on the receive path and can reject a notification before the client starts any history-sync activity.
Leaving the policy unset keeps the default behavior at zero cost. The receive path only checks that the optional policy is None.
This is an opt-in seam. Rejecting a notification is a deliberate decision to drop a chunk the phone offered; the SDK will never do this on its own.
When to use it
Consider a policy when:- You want to admit some history-sync types but not others (for example, accept
INITIAL_BOOTSTRAPbut rejectRECENT). - You want to bound per-chunk cost with a size guard on
file_lengthorinline_payload_len. - You want to drop peer-data-request responses that your bot never issued.
- You need finer control than the all-or-nothing
.skip_history_sync()toggle already exposes.
.skip_history_sync() if you want to drop every history-sync notification unconditionally. That toggle is simpler and takes precedence over any registered admission policy — the policy is not consulted when skip_history_sync is on.
Registration for device pairing and the require_full_sync request are unchanged. The policy runs after pairing completes and only gates the delivery of individual history-sync chunks from the phone.
Scope
The policy is consulted for every inbound history-sync notification that reacheshandle_history_sync, except in two cases:
- The client is shutting down (the notification is dropped without consulting the policy or sending a receipt).
skip_history_syncis enabled (the client sends ahist_syncreceipt and never calls the policy).
RejectAndAcknowledge decision:
- Sends a
hist_syncreceipt so the phone considers the chunk delivered and stops re-uploading it. - Does not enqueue the notification onto the major-sync worker.
- Does not emit
Event::HistorySync.
RejectAndAcknowledge is not a way to shed load and get the chunk back later — the phone will not offer it again. If you need transient load shedding, do it inside Accept by throttling downstream work, not by rejecting.
Types
HistorySyncMetadata and HistorySyncDecision are #[non_exhaustive] — new fields or variants may appear in future releases. Match with a wildcard arm on HistorySyncDecision and treat missing metadata fields as unknown rather than empty.
HistorySyncAdmission is object-safe and WASM-safe (MaybeSendSync is Send + Sync on native targets, unbounded on wasm32). It is re-exported from the crate root alongside HistorySyncMetadata and HistorySyncDecision.
decide runs inline on the receive path and is deliberately synchronous. A slow or awaiting policy would stall history-sync intake. Keep it to a fast local decision (a comparison, an atomic counter, a bitmask over sync_type); do no I/O or blocking inside it.
Metadata fields
Opting in
Register the policy on the builder before the client connects. BothBot::builder() and ClientBuilder expose the same method.
Arc, use with_history_sync_admission_arc to avoid re-boxing:
Example: cap chunk size
Drop any chunk whose sender-declared file size exceeds a threshold, and accept everything else.file_length is sender-declared and not validated, this is a best-effort gate. A chunk whose actual payload exceeds the declared size will still be admitted if the declared value is under the cap; use the standard memory-report counters to observe realised cost.
Precedence
Two related settings take precedence over the admission policy:- Shutdown. During shutdown the notification is dropped silently, without a receipt and without consulting the policy.
skip_history_sync. When on, the client sends ahist_syncreceipt and skips the policy. Change the toggle at runtime withClient::set_skip_history_sync.
require_full_sync and history_sync_config fields set at pairing time are independent of this hook. They shape what the phone offers; the admission policy shapes what the client accepts once the phone offers it.
See also
- Retry Admission Hook — the sibling opt-in policy for gating inbound group/status retry receipts.
- Inbound Durability Hook — the opt-in hook idiom this trait follows.
Bot.skip_history_sync— the all-or-nothing toggle that takes precedence over any admission policy.