WhatsApp bans accounts that send too many messages in a short period. The Baileys provider’s built-in rate limiter protects your bot automatically — it’s enabled by default and sits inside the provider’s outbound send pipeline, so every ctx.reply(), bot.send(), bot.broadcast() and media send passes through it.
Transport-owned pacingThe pacing policy lives on the transport provider, not on the
core: each transport may enforce its own limits (Telegram 429s, Discord
buckets, Cloud API tiers — surfaced as typed RateLimitedErrors). This
page covers the WhatsApp (Baileys) token-bucket limiter you configure when
constructing BaileysProvider.
The limiter uses a token bucket algorithm with two independent buckets:
Per-chat — limits how fast you can send to a single conversation.
Global — limits your total outbound throughput across all chats.
When a bucket is empty, messages are queued (not dropped) and released as tokens refill; a throttled chat does not hold the others back. A send that waits in the queue longer than maxWait (30 s by default) rejects with RateLimiterTimeout, a RateLimitedError, so a caller never hangs. An optional jitter adds a random human-like delay between sends.
New accounts are more sensitiveA freshly registered WhatsApp number gets banned faster than an aged one. Start conservative (3 / 10s per chat, 20 / 60s global) and increase gradually.
Whatever the transport, a ctx send (reply, say, media, in handlers, flows
and conversations) that the provider rejects with a RateLimitedError asking
for a short wait is retried in place, so a conversation step does not end on a
transient 429: by default once, when retryAfterMs is at most 5 s.
BotConfig.rateLimitRetry tunes it (retries counts attempts after the first):
new Bot({ provider, rateLimitRetry: { retries: 2, maxWaitMs: '10s' } })new Bot({ provider, rateLimitRetry: false }) // never retry in place
A longer wait, other errors and bot.send() are not retried in place: they
reject with the provider’s error. bot.broadcast()
(its retries option) and the durable outbox have their own back-off.
The rate limiter runs afterbefore('send') hooks but before the actual provider send. If a hook aborts the send, the rate limiter is never consulted — aborted sends don’t consume tokens.
Assistant
Responses are generated using AI and may contain mistakes.