Gateway
How to use the Gateway plugin in Carbon to receive non-webhook events from Discord.
If you've been around Discord bots for a while, you're probably familiar with the Gateway - it's the WebSocket connection that bots use to receive real-time events from Discord. While HTTP interactions are great for slash commands and buttons, sometimes you need to know when a user joins a server, when a message is sent, or when someone's voice state changes. That's where the Gateway plugin comes in.
Carbon provides two plugins for handling Gateway connections: the GatewayPlugin
for single-process bots and the ShardingPlugin
for when your bot grows bigger. Let's dive into how they work and when to use each one.
The Basics
Think of Discord's Gateway as a constant phone line between your bot and Discord. Instead of your bot having to constantly ask "did anything happen?", Discord just tells you when something happens. This is super efficient, but it means your bot needs to maintain a constant connection.
Under the hood, the Gateway plugin takes care of all the complex stuff for you. It starts by fetching and caching the WSS URL from Discord's API, then establishes a secure WebSocket connection and handles the initial handshake process. Once connected, it manages everything about the connection - sending regular heartbeats at Discord's specified interval, monitoring the acknowledgments to make sure the connection is healthy, and even responding to Discord's own heartbeat requests when they come in.
The plugin also handles all the session management details. It keeps track of your session ID and resume URLs from the Ready events, handles any disconnections with the proper close codes, and tries to resume sessions when possible. If resuming isn't an option, it'll fall back to starting a fresh connection. And of course, it implements proper error recovery with exponential backoff for reconnections, queues events during reconnection attempts, and handles all the rate limits and throttling that Discord requires.
If you're building a serverless bot or prefer HTTP-based interactions, check out our HTTP bots guide. Or, if you want the best of both worlds, take a look at our Gateway Forwarder plugin which lets you receive Gateway events through webhooks.
Setting Up the Gateway Plugin
The Gateway plugin handles all the connection management, but you need to tell it which events you want to receive through Gateway Intents. Intents are Discord's way of optimizing traffic - you only get the events you actually need.
Here's a basic setup:
When choosing your intents, think about what your bot actually needs. For example, if you want to know when messages are sent, you'll need the GuildMessages
intent. If you want to read the actual content of those messages, you'll also need the MessageContent
intent. For server events like joins and leaves, you'll want the Guilds
intent. Some intents like GuildMembers
and GuildPresences
are considered "privileged" and need to be specifically enabled in your Discord application settings.
Handling Events
Once you've got the Gateway plugin set up, you'll need to create listeners to handle the events you receive. Head over to our Listeners guide to learn how to handle messages, member updates, and other Gateway events.
Scaling with Sharding
When your bot joins more than 2,500 servers, Discord requires you to use sharding. But don't worry - our ShardingPlugin
makes this super easy. Instead of managing multiple Gateway connections yourself, just swap out the GatewayPlugin
for the ShardingPlugin
:
The plugin will automatically figure out how many shards you need by querying Discord's API. Behind the scenes, Discord uses a formula to determine which shard handles which guild: shard_id = (guild_id >> 22) % num_shards
. But don't worry about that math - the ShardingPlugin handles all of it for you!
Connection Lifecycle
The Gateway connection follows a specific lifecycle that Discord has defined. It starts with the initial connection, where we fetch the Gateway URL from Discord's API, open a WebSocket connection, and receive a Hello event with our heartbeat interval. Then comes the handshake phase, where we start sending regular heartbeats and send our Identify payload with our token and intents. Once Discord sends us a Ready event with our session details, we're in business!
During normal operation, we keep sending those heartbeats on schedule and process any Gateway events that come in. We're always watching those heartbeat acknowledgments too - they're our canary in the coal mine for connection health. If something goes wrong and we get disconnected, we first try to detect what happened (maybe we missed an ACK, or maybe we got a specific close code). Then we'll try to resume our session if it's still valid, or fall back to starting fresh if we need to. And of course, we use exponential backoff when reconnecting to avoid overwhelming Discord's servers.
Quick Tips
Starting out with Gateway connections? Here's what you need to know: Start with the GatewayPlugin
if your bot is in fewer than 2,500 servers - it's simpler and works great for most bots. When you do need to scale up, let Discord tell you how many shards to use - the ShardingPlugin
will automatically query Discord's API to get the right number.
Only request the intents you actually need - this helps your bot run more efficiently and keeps Discord's servers happy. And remember that some intents (like MessageContent
) are "privileged" and need to be enabled in your Discord application settings. Keep an eye on your connection health through events like RESUMED
, READY
, and INVALID_SESSION
.
Don't forget about the basics either - always use proper User-Agent headers in your requests to Discord's API, and make sure you're handling rate limits properly (though the plugins do this automatically). If you run into any issues or have questions, join our Discord server - we're always happy to help!
Last updated on