When your Discord bot loses connection during a brief network hiccup, it may attempt to reconnect hundreds of times per minute. This rapid reconnect cycle, known as a WebSocket reconnect storm, can cause rate limits, IP bans, and service degradation for your bot. The storm happens because the bot’s default reconnection logic does not wait long enough between attempts. This article explains why reconnect storms occur and provides concrete code-level fixes to stop them.
Key Takeaways: Stopping a Discord Bot WebSocket Reconnect Storm
- Exponential backoff with jitter: Prevents rapid reconnection by doubling wait times and adding randomness.
- Discord.js Client reconnect settings: Set
reconnectDelayandmaxReconnectAttemptsin client options. - Library-agnostic guard logic: Track reconnect timestamps and skip attempts if under a minimum interval.
Why WebSocket Reconnect Storms Happen
A Discord bot maintains a persistent WebSocket connection to receive events. When the network drops for even a fraction of a second, the bot’s WebSocket library detects the disconnection and immediately fires a reconnect event. Without a delay, the bot sends a new connection request instantly. If the network is still unstable, the new connection fails, and the cycle repeats.
Discord’s Gateway API expects clients to use exponential backoff — waiting 1 second, then 2, then 4, and so on — before attempting to reconnect. Many bot libraries default to immediate reconnection. This violates Discord’s rate limits and can result in your bot being temporarily blocked from the Gateway.
The Role of the Discord Gateway
The Gateway is the WebSocket endpoint that delivers real-time events like messages, member updates, and voice state changes. Each bot session must maintain one Gateway connection. When a reconnect storm occurs, the bot opens and closes multiple Gateway connections in seconds. Discord’s server-side throttling kicks in, returning HTTP 429 (Too Many Requests) or even closing the connection with a 4004 (Authentication Failed) error.
Steps to Fix the WebSocket Reconnect Storm
These steps apply to Discord.js v14 and similar libraries. Adjust variable names if using discord.py or other wrappers.
- Enable Exponential Backoff in Client Options
In Discord.js, setreconnectDelayandmaxReconnectAttemptswhen creating the client. Example:const client = new Client({ intents: [GatewayIntentBits.Guilds], reconnectDelay: 1000, maxReconnectAttempts: 10 });This tells the library to wait 1 second before the first retry and double the delay each time. - Add Jitter to Prevent Thundering Herd
Jitter adds random milliseconds to the delay so that multiple bot instances do not reconnect simultaneously. In Discord.js, you can implement jitter in thereconnectingevent:client.on('reconnecting', () => { const jitter = Math.random() 2000; setTimeout(() => client.login(token), 1000 + jitter); });This spreads out reconnect attempts. - Implement a Connection State Guard
Track the last reconnect timestamp in a variable. If a reconnect event fires within 5 seconds of the last attempt, skip it. Example:let lastReconnect = 0; client.on('reconnecting', () => { const now = Date.now(); if (now - lastReconnect < 5000) return; lastReconnect = now; // proceed with reconnect }); - Use the Official Discord.js Reconnect Module
The@discordjs/wspackage provides built-in exponential backoff. Replace raw WebSocket code withWebSocketManagerfrom that package. Install withnpm install @discordjs/wsand configurereconnectAttemptsandreconnectDelayin theWebSocketManagerOptions. - Monitor Gateway Latency and Disconnect Codes
Log the WebSocket close code on every disconnect. Codes 1000 (normal closure) and 1001 (going away) are safe to ignore. Code 4009 indicates session timeout — increase your reconnect delay to at least 10 seconds. Code 4004 means invalid token — stop reconnecting immediately and alert the administrator.
If the Bot Still Reconnects Too Aggressively
Bot Reconnects Even After Implementing Backoff
Some bot libraries, especially older versions of discord.py, do not respect custom reconnect delays. Upgrade to the latest library version. For discord.py 2.3+, set reconnect=True and the library handles backoff automatically. If using a custom WebSocket library, ensure you are not calling connect() inside the on_disconnect event — that creates a loop.
Rate Limit (HTTP 429) Still Appears
If your bot receives 429 errors after fixing the reconnect storm, the rate limit may be from another part of your code, such as message sending or REST API calls. Check the Retry-After header in the 429 response. Implement a global rate limiter using @discordjs/rest’s built-in bucket handling. Do not ignore 429 responses — they can escalate to a permanent ban.
Bot Goes Offline After Network Recovers
If the bot stops reconnecting entirely after a network hiccup, your reconnect guard may be too strict. Reduce the minimum interval from 5 seconds to 2 seconds and ensure the guard resets after a successful connection. Add a client.on('ready', () => { lastReconnect = 0; }) to clear the guard on successful login.
Reconnect Storm Prevention: Code-Level vs Library-Level
| Item | Code-Level Guard | Library-Level Option |
|---|---|---|
| Implementation effort | Write custom logic in events | Set config values in constructor |
| Flexibility | Full control over delay and jitter | Limited to library defaults |
| Risk of blocking | Possible if guard logic is wrong | Low — library handles edge cases |
| Best for | Custom WebSocket implementations | Discord.js, discord.py, JDA users |
Use library-level options first. They are tested by thousands of bots. Add a code-level guard only if the library does not support backoff or if you need custom jitter values.
After applying the fixes above, your bot will survive network hiccups without triggering reconnect storms. Test the behavior by disconnecting your internet for 10 seconds while the bot is running. Watch the logs — you should see a single reconnect attempt after a delay, not a flood. For production bots, also enable Gateway intent logging to track session resumptions. A healthy bot resumes its session without re-identifying, which saves bandwidth and avoids rate limits.