Rate Limits and Ban Risk
Control queue pressure, handle provider rejection, and understand what this project can and cannot promise about WhatsApp restrictions.
open-wa does not expose a WhatsApp rate-limit guarantee. WhatsApp does not publish a stable per-chat or per-group rate table, and provider restrictions can change without notice, so a local queue is a pacing control rather than a ban avoidance mechanism.
What is known and what is not
The client and schema define how open-wa validates and dispatches a send. They do not define WhatsApp's server-side quota, rolling window, account-age rule, or restriction duration. Treat community measurements as dated observations that need their own evidence; this guide does not turn them into defaults.
Provider rejection can happen even when a local queue is obeying its schedule. Handle the rejected operation, stop or slow the relevant workflow, and record the provider error before deciding whether a retry is appropriate. Do not retry in a short loop, and do not assume that a random delay makes a pattern safe.
Queue concurrency and rate are different
concurrency limits how many queue tasks run at the same time. It does not set
the time between tasks. In p-queue, intervalCap and interval implement an
interval window; omitting intervalCap leaves the cap at its default of
Infinity. The following example uses strict rolling-window mode to allow no
more than one queued send in any 15-second span, runs one task at a time, and
records rejected jobs:
import PQueue from 'p-queue';
import { Client, createClient } from '@open-wa/wa-automate';
import { PuppeteerDriver } from '@open-wa/driver-puppeteer';
const runtime = await createClient({
sessionId: 'paced-sender',
driver: new PuppeteerDriver(),
});
const client = new Client({
client: runtime,
transport: runtime.getTransport(),
});
const sendQueue = new PQueue({
concurrency: 1,
intervalCap: 1,
interval: 15_000,
strict: true,
});
async function enqueueSend(chatId: string, text: string) {
try {
const result = await sendQueue.add(() => client.sendText(chatId, text));
if (result === false) {
console.error('WhatsApp did not accept the send request', { chatId });
return false;
}
return result;
} catch (error) {
console.error('WhatsApp rejected a queued send', { chatId, error });
throw error;
}
}
await client.start();
await enqueueSend('447700900000@c.us', 'Hello');Install the example dependencies with npm install @open-wa/wa-automate@5.1.0 @open-wa/driver-puppeteer@5.1.0 p-queue. Complete the normal client authentication when it starts. This is a process-local schedule: it does not coordinate other sessions or senders and does not establish a provider quota. Choose the interval for your workflow, consent model, and operational budget, then stop or reclassify work when WhatsApp reports a restriction.
Safer workflow boundaries
- Accept messages or jobs only from a bounded source so a traffic spike cannot create an unbounded backlog.
- Keep consent and opt-out state beside the job, and remove opted-out recipients before enqueueing a send.
- Keep one clear owner for retries. A queue retry and an application retry can multiply traffic if both act on the same rejection.
- Record the chat ID, operation, result, and provider error without logging message contents or credentials by default.
- Stop or pause the queue after repeated rejections and require an operator to decide whether the workflow should resume.
Handling a restriction
There is no documented universal wait time for a WhatsApp restriction. Stop the automation, retain the provider warning or error, and review consent, queue depth, duplicate sends, retry behavior, and account context. Resume only after you have a bounded plan and a reason to believe the provider state allows it; timing alone cannot establish that the account is clear.
Related
- AI Agent Patterns: Separate model concurrency from outbound pacing
- Messages guide: Handle send results and provider failures
- p-queue interval options:
intervalCap,interval, andconcurrency
Was this helpful?
Your answer includes the page path and docs version.
