Learn Bot Sharding With Discord.js
When a Discord bot grows to a certain size, normally around 2000 joined servers, a single instance of the bot will start to struggle with all this computation. This is where sharding comes in. Sharding is a method defined in the Discord developer documentation that allows you to run multiple instances of the same bot, splitting the share of servers between all instances.
Let’s say that you’ve created the next big Discord bot. Things are going really well, and your bot has been added to nearly 2000 servers. But your bot is struggling, in fact, it’s crashed a few times. So to handle this bandwidth you set up a second instance of your bot, and the instances takes ~1000 servers each. This is sharding in action. Now, you can’t just run two instances of the bot, you have to define a shard manager to split the work between the two.
Today, you’ll learn how to set up sharding with Discord.js and a few tricks to keep all your bot’s features working, even when running two instances via a sharding manager.
Create a bot (Optional)
If you already have a Discord bot written in Discord.js, you can safely skip this step. For those who haven’t, let’s create a simple NPM project and add a simple bot.
mkdir pingbot
cd pingbot
npm init -y
npm i discord.js
After creating the NPM project and installing Discord.js, create an index.js
file in that directory and add the following bot code. Then add your bot token and run the project with node .
to test that it’s working.
const { Client, Intents } = require('discord.js')const BOT_TOKEN = 'BOT_TOKEN_HERE'let client = new Client({
intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES]
})client.on('messageCreate', message => {
if (message.content === 'ping') message.reply('Pong!')
})client.login(BOT_TOKEN)
Implement Sharding
So how do we shard our bot? Well, Discord.js has a built-in sharding manager to manage multiple instances of our bot on the same machine. Create a new file called shard.js
and import the ShardingManager
. Then create a manager
, giving it the bot entry file (index.js
) and the bot token. Note that you need to pass the token both in the shard manager and in the bot itself. There are some more options for the manager, which you can find in the Discord.js documentation.
const { ShardingManager } = require('discord.js')const BOT_TOKEN = 'BOT_TOKEN_HERE'const manager = new ShardingManager(`${__dirname}/index.js`, { token: BOT_TOKEN })
We can then listen to the shardCreate
event and log the id of a shard when it’s launched. Then, we’re ready to spawn our shards with .spawn()
.
manager.on('shardCreate', shard => console.log(`Launched shard ${shard.id}`))
manager.spawn()
Counting Servers
One issue you might come across when sharding, is trying to show the number of servers your bot has joined. This is a common feature in either a bot’s status, or a /status
command. If you try to fetch the number of servers your bot is in with client.guilds.cache.size
, you might be surprised to see it return a number far lower than the real number. This is only the number of servers being served to this individual shard. To get the total number, we can use the following snippet to get the number of servers in each shard, and then add them all up before returning that value in a promise.
function totalGuilds() {
return client.shard.fetchClientValues('guilds.cache.size')
.then(shards => {
return shards.reduce((acc, guilds) => acc + guilds, 0)
})
}
You can use a similar trick to fetch a total member count. This time using the broadcastEval
method which sends code to all shards to evaluate and returns promise containing the array of responses.
function totalMembers() {
return client.shard
.broadcastEval(c => c.guilds.cache.reduce((acc, guild) => acc + guild.memberCount, 0))
.then(shards => shards.reduce((acc, memberCount) => acc + memberCount, 0))
}
Conclusion
Sharding is required for bots over a certain size, and splitting the bot into multiple instances will help performance once you reach that size. Discord.js makes it easy to get set up with sharding, so if you have a bot that is growing fast, keep this in mind and maybe start implementing it now. You can also run a single shard instance if you want to plan things out ahead of time.
You can only scale vertically so much, so soon I’ll be working on a second part to this article explaining how to shard your discord bot over multiple physical machines.
More content at plainenglish.io. Sign up for our free weekly newsletter. Get exclusive access to writing opportunities and advice in our community Discord.