Discord API Rate Limits: Understanding and Handling Them Properly

Published on

How to handle Discord API rate limits in your bot. Covers rate limit types, headers, queuing strategies, and preventing bans from aggressive API usage.

Written by Space-Node Team – Infrastructure Team – 15+ years combined experience in game server hosting, VPS infrastructure, and 24/7 streaming solutions. Read author bio →

Discord rate limits are the guardrails that keep the API usable for everyone. Hit them too hard and Discord will slow your bot down, or even ban it. Understanding them prevents both.

How Rate Limits Work

Every Discord API endpoint has a rate limit - a maximum number of requests per time window. When you exceed the limit:

  1. Discord returns HTTP 429 (Too Many Requests)
  2. The response includes Retry-After header with wait time
  3. Your bot must wait before making more requests

Rate Limit Types

Per-Route Limits

Each API endpoint has its own limit:

  • Send message: 5 per 5 seconds per channel
  • Edit message: 5 per 5 seconds per channel
  • Delete message: 5 per 1 second per channel (special rate)
  • Bulk delete: 1 per 1 second per channel
  • Reactions: 1 per 0.25 seconds per channel

Global Limits

50 requests per second across all endpoints. Exceeding this affects all bot operations.

Per-Resource Limits

Some limits are per-guild or per-channel, not per-bot. Multiple bots in the same guild share these limits.

How discord.js Handles It

discord.js has built-in rate limit handling:

const client = new Client({
    rest: {
        timeout: 15000,
        retries: 3
    }
});

It automatically:

  • Queues requests when approaching limits
  • Waits when receiving 429 responses
  • Retries failed requests

Rate Limit Events

client.rest.on('rateLimited', (info) => {
    console.warn(`Rate limited: ${info.route} - Retry after ${info.retryAfter}ms`);
});

Common Mistakes

Spamming Messages

// BAD: Sends 100 messages instantly, hits rate limit
for (const user of users) {
    await channel.send(`Hello ${user}!`);
}

// GOOD: Batch into one message
const userList = users.map(u => u.toString()).join(', ');
await channel.send(`Hello ${userList}!`);

Mass Operations

// BAD: Banning 50 users simultaneously
users.forEach(async user => {
    await guild.members.ban(user);
});

// GOOD: Sequential with delay
for (const user of users) {
    await guild.members.ban(user);
    await new Promise(resolve => setTimeout(resolve, 1000)); // 1s between bans
}

Reaction Spam

// BAD: Adding 10 reactions instantly
emojis.forEach(async emoji => {
    await message.react(emoji);
});

// GOOD: Sequential with delay for reaction rate limit
for (const emoji of emojis) {
    await message.react(emoji);
    await new Promise(resolve => setTimeout(resolve, 300));
}

Prevention Strategies

Request Caching

Don't request data you already have:

// BAD: Fetching channel every time
async function sendMessage(channelId, content) {
    const channel = await client.channels.fetch(channelId);
    await channel.send(content);
}

// GOOD: Use cache first
async function sendMessage(channelId, content) {
    const channel = client.channels.cache.get(channelId) 
        || await client.channels.fetch(channelId);
    await channel.send(content);
}

Bulk Operations

Use bulk endpoints when available:

// Instead of deleting messages one by one:
await channel.bulkDelete(50); // Deletes up to 100 messages in one request

Queue System

For features that could generate many API calls:

const actionQueue = [];
let processing = false;

function queueAction(action) {
    actionQueue.push(action);
    if (!processing) processQueue();
}

async function processQueue() {
    processing = true;
    while (actionQueue.length > 0) {
        const action = actionQueue.shift();
        try {
            await action();
        } catch (error) {
            if (error.httpStatus === 429) {
                actionQueue.unshift(action); // Re-queue
                await new Promise(resolve => setTimeout(resolve, error.retryAfter));
            }
        }
        await new Promise(resolve => setTimeout(resolve, 100)); // Minimum delay between actions
    }
    processing = false;
}

Monitoring

Track your rate limit hits:

let rateLimitCount = 0;

client.rest.on('rateLimited', () => {
    rateLimitCount++;
});

setInterval(() => {
    if (rateLimitCount > 0) {
        console.log(`Rate limits hit in last hour: ${rateLimitCount}`);
        rateLimitCount = 0;
    }
}, 3600000);

If rate limit hits increase over time, your bot needs optimization.

What Happens if You Ignore Limits

  1. Cloudflare ban: Persistent 429 abuse results in your bot's IP being temporarily banned by Discord's CDN
  2. Token revocation: Extreme abuse leads to your bot token being revoked
  3. API ban: Your application can be banned from the API entirely

Take rate limits seriously. They protect both Discord and your bot's reliability. On Space-Node hosting, your bot has a stable IP and connection - consistent rate limit handling is easier when your network is reliable.

Space-Node Team

About the Author

Space-Node Team – Infrastructure Team – Experts in game server hosting, VPS infrastructure, and 24/7 streaming solutions with 15+ years combined experience.

Since 2023
500+ servers hosted
4.8/5 avg rating

Our team specializes in Minecraft, FiveM, Rust, and 24/7 streaming infrastructure, operating enterprise-grade AMD Ryzen 9 hardware in Netherlands datacenters. We maintain GDPR compliance and ISO 27001-aligned security standards.

View Space-Node's full team bio and credentials →

Launch Your VPS Today

Get started with professional VPS hosting powered by enterprise hardware. Instant deployment and 24/7 support included.

Discord API Rate Limits: Understanding and Handling Them Properly