Skip to content

Token Bucket Algorithm

A rate-limiting algorithm in which tokens refill at a fixed rate up to a capacity and each request spends one, allowing short bursts but a steady average.

Also called: Token bucket · Token bucket rate limiter

Reviewed

Interactive lab

Hands on: use the controls to explore. Anything that plays on its own pauses while you are working inside it.

Fire a burst of sends at the bucket

Refill +60 / s

0 / 20 tokens

Each dot = 1 token

Last burst · 100 sends

20 admitted — one token each. 80 rejected with HTTP 429 Too Many Requests: the bucket ran dry. Each chip ≈ 2.5 sends.

Tokens left
0
Admitted
20
Rejected (429)
80
Full again in
333 ms
60 tokens / s

The bucket holds 20 tokens, so up to 20 sends can go out in one burst. After that, sends get through only as fast as tokens drip back in: 60 per second is the sustained limit. Watch the dots refill, then send another burst before it is full.

A 20-token bucket refilling at 60 per second, so no one-second window exceeds 80 sends. Fire a burst: 20 go at once and the rest are refused here — a client-side pacer would hold them until tokens drip back.

A burst of 100 hit a full bucket of 20: 20 accepted, 80 rejected with 429.

01What is the token bucket algorithm?

The token bucket algorithm limits the rate of events while still allowing short bursts. Picture a bucket that holds at most C tokens and is topped up at a steady r tokens per second. Every request must take a token before it goes ahead: if one is available it proceeds at once; if the bucket is empty it waits for the next token or is refused. Over the long run requests can never exceed r per second, yet after a quiet spell up to C can go out back to back.

Two numbers fully describe a bucket, and they do different jobs. The capacity C is the burst allowance — how many requests can leave together when the bucket is full. The refill rate r is the sustained throughput. An implementation needs no timer: it stores the token count and the time of the last update, and on each request adds elapsed × r tokens (capped at C) before checking whether one can be spent.

WhatsApp senders usually run the algorithm on their own side, to pace outbound sends below what the platform allows. A Cloud API phone number has a default throughput of up to 80 messages per second, exceeding it returns error 130429, and sending too fast to a single recipient trips a separate pair rate limit (error 131056). That is the difference from rate limiting, which describes the limits Meta enforces, and from backpressure, the signal that tells producers upstream to slow down when your bucket and queue fill up.

Key takeaways

  • The token bucket algorithm refills tokens at a fixed rate up to a capacity; each request spends one and waits, or is refused, when none are left.
  • Capacity sets the largest burst; the refill rate sets the long-run average throughput.
  • Run one client-side to pace sends under a WhatsApp number's throughput, which is up to 80 messages per second by default.
  • In any one-second window a bucket can release its capacity plus one second of refill, so keep the two together under the limit.
  • The token bucket is what you run yourself; rate limiting is what Meta enforces when you do not, answering with error 130429.

02 · How it works, step by step

How does the token bucket algorithm work?

  1. Step 1

    Choose the rate

    Set the refill rate a little under the limit you must respect — for a number on the default 80 messages per second, perhaps 60 to 70 — leaving headroom for retries and other senders on the same number.

  2. Step 2

    Choose the capacity

    Pick the burst you are willing to release at once. If no one-second window may exceed 80 sends, keep capacity plus refill rate at or below 80 — for example 20 tokens refilling at 60 per second.

  3. Step 3

    Spend a token per send

    Before each Cloud API call, take a token. If none is left, wait until the next one is due instead of sending anyway and collecting a 130429.

  4. Step 4

    Share one bucket per number

    Workers sending from the same number need one bucket, held by a single dispatcher or in a shared store updated atomically (for example a Redis script). A bucket per worker multiplies the rate.

  5. Step 5

    Add small buckets per recipient

    Keep a small bucket per recipient as well, so a flurry of messages to one customer cannot trip the pair rate limit while the number-level bucket still has tokens.

  6. Step 6

    Adapt when the platform pushes back

    If 130429 or 131056 still appears, lower the refill rate for a while and raise it slowly. Those errors are the signal that your settings are too optimistic.

03The token bucket algorithm in code

export class TokenBucket {
constructor({ capacity, refillPerSecond }) {
this.capacity = capacity;
this.rate = refillPerSecond;
this.tokens = capacity;
this.updated = performance.now();
}
#refill() {
const now = performance.now();
const elapsed = (now - this.updated) / 1000;
this.tokens = Math.min(this.capacity, this.tokens + elapsed * this.rate);
this.updated = now;
}
/** Resolves once a token has been taken. */
async take() {
for (;;) {
this.#refill();
if (this.tokens >= 1) {
this.tokens -= 1;
return;
}
const waitMs = ((1 - this.tokens) / this.rate) * 1000;
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
}
}
// 20 + 60 <= 80: never more than 80 sends in any one-second window.
const bucket = new TokenBucket({ capacity: 20, refillPerSecond: 60 });
for (const job of jobs) {
await bucket.take();
sendTemplate(job); // POST https://graph.facebook.com/v26.0/{PHONE_NUMBER_ID}/messages
}

A pacer waits for the next token instead of refusing the send. The send itself is not awaited, so slow responses do not reduce the rate.

04The token bucket algorithm: key facts and limits

Parameters
Capacity C (burst) and refill rate r (tokens per second)
Most released in any 1-second window
C + r
Long-run maximum rate
r per second
Default Cloud API throughput
Up to 80 messages per second per number
Upgraded throughput
1,000 messages per second, automatic when eligible
Errors when you exceed limits
130429 (throughput), 131056 (pair rate limit)

05Why does the token bucket algorithm matter?

Without pacing, a broadcast or a post-outage recovery fires as fast as the workers allow, hits the throughput ceiling within a second and spends the rest of the run retrying 130429 errors — slower overall than sending at the right rate from the start. A token bucket turns 'as fast as possible' into 'as fast as allowed', keeps bursts within limits you choose, and gives every worker one shared rule, so throughput is predictable and OTPs are not starved by marketing traffic.

06Example: Pacing a Thrissur jeweller's festive broadcast

A Thrissur jeweller sends a Dhanteras offer to 60,000 opted-in customers from a number on the default throughput of up to 80 messages per second. The first attempt, with no pacing, ran 20 workers flat out: within a second 130429 errors appeared and retries dragged the run out. With one shared bucket of 20 tokens refilling at 60 per second, the send settles at a steady 60 messages per second and finishes in under 17 minutes without throughput errors, while the remaining headroom on the number keeps login OTPs flowing.

07 · Common mistakes, and the fix

Common mistakes with the token bucket algorithm

  • One bucket per worker

    Ten workers each pacing at 60 per second send 600 per second from the same number. The bucket must be shared, in one dispatcher or an atomic shared store.

  • Forgetting the burst

    A full bucket of 80 tokens refilling at 80 per second can release 160 sends in one second. Size capacity and rate together against the window the limit is measured over.

  • Refusing instead of waiting

    A server-side limiter answers 429; a client-side pacer should hold the send until a token is due. Dropping sends to stay under a limit loses messages.

  • Ignoring per-recipient limits

    A number-level bucket does not stop five order updates to one customer in the same second. Add a per-recipient bucket or combine messages to the same person.

  • Settings that never change

    When a number is upgraded to 1,000 messages per second, a bucket still tuned for 80 wastes most of the capacity. Read the number's current throughput and adjust.

08 · Tips from the bench

Best practices for the token bucket algorithm

  • Give OTPs and other critical traffic their own bucket or priority on the same number.
  • Log how long each send waited for a token; rising waits mean you need more throughput, not more workers.
  • Use a monotonic clock (performance.now(), Redis TIME) so a clock change can never mint tokens.
  • Cut the refill rate automatically when 130429 appears, then restore it gradually.

09Token Bucket Algorithm FAQs

What is the difference between a token bucket and a leaky bucket?+
A token bucket allows bursts up to its capacity, then a steady rate; a leaky bucket used as a queue releases requests at a constant rate with no bursts. Token buckets suit APIs that tolerate short bursts, leaky buckets suit strict smoothing.
How do I choose token bucket capacity and refill rate?+
Set the refill rate to the sustained rate you want, a little below the limit, and the capacity to the largest burst you can afford. If the limit applies per second, keep capacity plus refill rate at or below it.
Does WhatsApp use a token bucket?+
Meta does not publish how its limits are implemented. What matters is the documented behaviour: up to 80 messages per second per number by default, error 130429 when you exceed it, and a separate pair rate limit per recipient.
Should the token bucket run on the client or the server?+
Both have a place. Run one client-side to pace your own sends under Meta's limits, and one server-side if you expose an API and need to protect it from your own callers.

From definition to your first message

InfiQ is an official Meta Business Partner. Start a 7-day free trial — no card needed — and see this running on your own number.