← Back to blog

Developers: 50 req/s Limit, Queues Keep Discord Trading Alerts Live

September 11, 2026
Developers: 50 req/s Limit, Queues Keep Discord Trading Alerts Live

Discord caps every bot and IP at about 50 requests per second globally, with tighter per-route and per-webhook budgets layered on top. The moment you hit any of these, you get a 429 response with a retry_after value in seconds. Read it, honor it, and pause the affected queue. Guess wrong on timing or ignore the header entirely, and repeated invalid requests can trigger a temporary Cloudflare-level ban that takes down your whole alert pipeline, not just one channel.


TL;DR:

  • Bots should implement local token-bucket limits and per-channel queues to prevent exceeding Discord’s global and per-resource rate limits.
  • Always respect the retry_after header on 429 responses and add a small buffer to avoid edge-case race conditions.
  • Payload validation before sending reduces invalid requests and prevents triggering Cloudflare-level bans caused by malformed or oversized payloads.
  • Webhook limits are tighter than REST API limits, with roughly five requests per two seconds per webhook, and shared buckets across multiple webhooks in the same channel can lower throughput.
  • Monitoring 429 responses and invalid request counts helps identify and fix rate-limiting issues early, avoiding disruptions during high-traffic events like trading alerts.

Scalping-algo
Keep Trading Alerts Moving
Scalping-Algo combines TradingView indicators, native webhook alerts, and a Command Center for short-term trading workflows.
Explore Scalping-Algo

Table of Contents

Understanding Discord Alerts Rate Limits Layer by Layer

Discord doesn't run one rate limit. It runs several, stacked on top of each other, and each one fails differently.

At the top sits the global limit: 50 requests per second per bot token or IP. Blow past it and every subsequent request gets flagged with a global indicator in the 429 body, meaning the whole connection is throttled, not just one endpoint.

Below that are per-route (bucket) limits. Discord groups endpoints into buckets, and many buckets share scope across a resource. A channel, a webhook, or a guild can have its own bucket that multiple requests draw from simultaneously.

  • Global: approximately 50 req/s per bot/IP, hard ceiling across all endpoints
  • Per-route: individual buckets tied to specific endpoints (send message, edit channel, etc.)
  • Shared-resource: buckets scoped to a channel or webhook, so parallel bots posting to the same channel compete for the same budget
  • Invalid-request limit: a large number of invalid requests (401, 403, 429 responses) within 10 minutes triggers a temporary IP ban from Discord's rate limit documentation

That last one catches people off guard. It's not about volume of valid traffic. It's about malformed requests, bad auth, and repeated 429s piling up. A buggy retry loop that ignores retry_after can burn through that 10,000-threshold faster than you'd expect.

Reading the Headers That Actually Control Your Send Rate

Every Discord API response carries rate limit headers, and treating them as optional is how bots end up throttled without knowing why.

HeaderWhat it tells you
X-RateLimit-LimitTotal requests allowed in the current window
X-RateLimit-RemainingRequests left before you hit the wall
X-RateLimit-ResetUnix timestamp when the window resets
X-RateLimit-Reset-AfterSeconds until reset, relative to now
X-RateLimit-BucketUnique ID for the shared limit bucket this route belongs to
X-RateLimit-ScopeWhether the limit is user, global, or shared
Retry-AfterSeconds to wait before retrying, sent with 429 responses

Prefer X-RateLimit-Reset-After over X-RateLimit-Reset. The former is relative and immune to clock drift between your server and Discord's; the latter depends on both clocks agreeing, which they often don't. Both Retry-After and Reset-After are seconds as floats, not milliseconds, and treating them as milliseconds means your bot idles for a fraction of a second when it should wait several, according to Discord's own documentation. Add a small buffer, 50 to 100 milliseconds, on top of whatever the header says. It costs you almost nothing and prevents edge-case races where you resume sending a few milliseconds too early.

Webhook and Payload Limits That Trip Up Alert Bots

Webhooks carry their own budget separate from your bot's REST calls, and it's tighter than most developers assume.

Separate webhook and REST request queues

Community-maintained guidance puts webhook execution at roughly 5 requests per 2 seconds per webhook bucket. Run three separate webhooks into the same channel, and they can share that bucket, meaning your effective throughput is lower than the sum of each webhook's individual limit.

Payload size matters just as much as request frequency:

  • Message content: 2,000 characters maximum
  • Embeds: 10 per message, 6,000 combined characters across all embed fields
  • Attachments: capped file sizes per message, varying by server boost level
  • Malformed payloads (missing required fields, oversized embeds) return 400 errors that still count toward your invalid-request budget

Validating payloads locally before you send, checking embed length, character counts, and attachment size, keeps you from spiking your invalid-request count and drawing a Cloudflare timeout for something you could have caught in code.

Building an Alert Pipeline That Doesn't Get Throttled

The fix isn't clever retry logic. It's architecture that respects the limits before you hit them.

  1. Queue per channel, not per webhook. Serialize outgoing messages to a channel through a single queue. This prevents the collision that happens when three services independently post to the same channel and unknowingly share a bucket, an idea backed by practical webhook guidance.
  2. Run a local token-bucket limiter as a safety net. Don't rely solely on header parsing after the fact. A token bucket that tracks your own send rate catches bursts before Discord ever sees them.
  3. Honor retry_after without exception. On a 429, wait exactly what the header says, then resume. For 5xx errors, apply exponential backoff with jitter. Never retry a 4xx that isn't a 429, since that's a request problem, not a timing problem, and cap total retries so a broken payload doesn't loop forever.
  4. Cache X-RateLimit-Bucket across processes. If your alert system runs multiple workers or containers, share bucket state between them so one worker doesn't blow the budget another worker is tracking.

Pro Tip: Log your 429 frequency as a health metric, not just an error to suppress. A sudden rise in 429s usually means your queue design or token-bucket limits need retuning, not that Discord changed something.

Gateway Limits and When to Shard

REST limits aren't the only ceiling. The Gateway (Discord's WebSocket connection) has its own budget: roughly 120 events per connection per 60 seconds, plus separate identify and session-start limits that cap how often a bot can reconnect.

Sharding becomes relevant well before you'd expect. Start planning around 2,000 guilds, and Discord requires sharding once you cross roughly 2,500, according to developer support guidance. One exception worth knowing: interaction callback and follow-up webhook endpoints are exempt from the global 50 req/s REST limit, though they still carry their own bucket constraints.

A Quick Diagnostic Checklist Before You Blame Discord

Most rate-limit incidents trace back to something fixable in your own code, not a Discord outage.

Log these three things at minimum: 429 counts per route, the retry_after value on each one, and how often X-RateLimit-Remaining hits zero. If invalid-response types (400s, 401s) climb alongside 429s, that's a payload problem, not a pacing problem.

  • Validate embeds and character counts before every send, not after a failure
  • Check attachment sizes and confirm your token is present and valid before the request leaves your process
  • On any 429, pause the specific queue tied to that bucket, don't halt the entire bot
  • Triage in order: parse headers, pause the affected queue, validate the payload that failed, then retry with backoff

Following this order keeps a single bad payload from cascading into a full Cloudflare ban.

Why Discipline Around Rate Limits Matters More for Trading Alerts

A rate limit isn't an inconvenience for a trading bot; if you become a victim, it's crucial to act to preserve evidence before crypto trading bot scams. It's the difference between a signal that arrives in time to act on and one that queues behind a Cloudflare cooldown. Queue-per-channel design and payload validation aren't defensive coding habits here, they're what keeps a real-time entry alert from looking like a false outage. When a system serializes sends and checks payloads before dispatch, delivery stays predictable even under bursty market conditions, which is exactly when alerts matter most.

— Tran

Get Your Alerts Delivered Without the Guesswork

Building your own queue-per-channel logic, token-bucket limiter, and payload validator from scratch works, but it's a lot of plumbing to maintain just to get a buy signal into a Discord channel on time. Scalping-algo's indicators come with native webhook alerts built into the Command Center, so validated, serialized delivery is already handled between your TradingView signal and your Discord server.

Scalping-algo

That means fewer invalid-request spikes, fewer messages stuck behind a shared-bucket collision, and no separate throttling layer for you to build and babysit. If you're already juggling entry and exit alerts across multiple channels, a tested pipeline like the one in Algo Master's 3-indicator system removes one entire category of infrastructure risk from your setup. Check out the full indicator suite and see how alert delivery is handled end to end before you write another line of retry logic.

Sources

FAQ

Why is Discord telling me I'm being rate limited?

You've exceeded either the global 50 requests/second ceiling, a per-route bucket limit, or a shared per-channel/webhook budget. Discord returns a 429 with a retry_after value telling you exactly how long to wait.

Why does my Discord bot get rate limited during high-traffic events?

Bots that send bursts of alerts or messages without a local throttling layer often exceed per-route or per-webhook buckets even while staying under the global limit. Adding a token-bucket limiter and queue-per-channel design prevents this.

How long does a Discord rate limit last?

It depends on which limit you hit. A standard 429 typically clears in the retry_after window, often a few seconds; a Cloudflare-level ban triggered by 10,000 invalid requests in 10 minutes, per Discord's documentation, can last considerably longer and affects your entire IP.

What triggers a Cloudflare ban versus a normal 429?

A normal 429 comes from exceeding a request-rate bucket and resolves once you wait out retry_after. A Cloudflare ban comes from accumulating too many invalid requests, malformed payloads, bad auth, repeated 429s, within a 10-minute window.

Should I retry every failed request automatically?

No. Retry 429s and 5xx errors with backoff, but never automatically retry a 4xx error like a malformed payload, since that request will keep failing and adds to your invalid-request count until you fix the payload itself.