BotNetwork

Rate limits explained for bot developers

A rate limit is a contract. Respect it and your bot is fast and reliable; ignore it and the platform slows you down, or shuts you out.

Published 3 min read

Why limits exist

Platforms share infrastructure between millions of bots and users. Limits protect that infrastructure and protect users from spam. For a bot developer they also define the maximum speed of anything you build: a broadcast to 10,000 users at 30 messages per second takes over five minutes no matter how fast your server is.

How limits are measured

Most APIs implement one of three algorithms. You can watch them side by side in the rate limiter playground.

  • Fixed window: N requests per window (for example per minute). Simple, but allows up to twice the limit around the window boundary.
  • Sliding window: counts requests in the last N seconds at any moment. Smoother and stricter.
  • Token bucket: a bucket refills at a steady rate; each request takes a token; short bursts are allowed up to the bucket size.

Limits also have a scope: per chat, per channel, per route, per bot or per app. A bot can be well under its global limit and still be throttled in a single busy chat.

The limits that matter most

Platform Documented limit Scope
Telegram About 1 message per second Per chat
Telegram 20 messages per minute Per group
Telegram About 30 messages per second Overall broadcasting
Discord 50 requests per second Global, per bot
Discord Varies, reported in headers Per route (bucket)
Slack Tiers from Tier 1 to Tier 4; chat.postMessage about 1 per second Per method, per workspace; per channel
WhatsApp Cloud API 80 messages per second by default Per business phone number

Exact figures, sources and last-checked dates are in our rate limits table. The comparison tool estimates how long a send of N messages takes on each platform.

Reading a 429

HTTP 429 Too Many Requests means "slow down". The response usually tells you for how long:

  • The standard Retry-After header, in seconds.
  • Telegram returns parameters.retry_after in the JSON body.
  • Discord returns retry_after in the body and X-RateLimit-* headers that describe the bucket, including X-RateLimit-Remaining and X-RateLimit-Reset-After, so you can slow down before hitting the limit.

Always wait at least the time the server asks for. Retrying immediately extends the penalty, and repeated invalid requests can get a bot temporarily blocked: Discord documents a limit on invalid requests (401, 403 and 429 responses) per IP address.

Backoff with jitter

For errors without a server-provided delay (timeouts, 502, 503), retry with exponential backoff and jitter: wait a random time between zero and a cap that doubles after each failure. The jitter prevents all your workers from retrying at the same instant. Limit the number of attempts and only retry idempotent operations, or use an idempotency key. The backoff calculator generates the schedule and code.

Throttle before you hit the limit

The best 429 is the one you never get:

  1. Put sends in a queue instead of calling the API from every handler.
  2. Throttle per scope: one token bucket per chat plus one global bucket.
  3. Spread broadcasts over time and send them at a rate below the documented limit, leaving headroom for interactive replies.
  4. Prioritize: replies to users first, bulk messages after.
  5. Track 429s as a metric. A rising count is an early warning.

Common mistakes

  • Treating limits as global when they are per chat (or the opposite).
  • Running several instances that each think they own the whole limit. Use a shared limiter (Redis, a Durable Object) or one sender process.
  • Retrying 4xx errors other than 429: a bad request will fail again.
  • Hard-coding limits without a source. Platforms change them; keep the number in configuration.

Sources