Sharding
Discord requires bots in more than 2,500 guilds to use sharding — splitting the bot across multiple processes, each managing a subset of guilds. Popii ships two utilities for this: autoShard (recommended) and PopiiShardingManager (manual).
When you need sharding
Section titled “When you need sharding”Discord’s hard limit is 2,500 guilds per shard. Below that, your bot runs in a single process and needs no changes. Above it, Discord will refuse Gateway connections unless you shard.
autoShard — recommended approach
Section titled “autoShard — recommended approach”autoShard queries Discord for the recommended shard count, then decides automatically:
- Below threshold → starts your bot as a normal single process (no overhead).
- At or above threshold → spawns a
PopiiShardingManagerwith the correct shard count.
Create a separate shard.ts entry point:
import { autoShard } from "popii-framework";
await autoShard({ token: process.env.DISCORD_TOKEN!, file: "./src/index.ts", // default — your normal bot entry point threshold: 2_500, // default — activate sharding above this guild count});Run shard.ts instead of src/index.ts in production:
{ "scripts": { "start": "bun run shard.ts", "dev": "bun run src/index.ts" }}Your src/index.ts stays unchanged — it doesn’t need to know about sharding.
PopiiShardingManager — manual control
Section titled “PopiiShardingManager — manual control”Use this when you want explicit control over the shard count or lifecycle:
import { PopiiShardingManager } from "popii-framework";
const manager = new PopiiShardingManager({ token: process.env.DISCORD_TOKEN!, file: "./src/index.ts", totalShards: "auto", // let Discord decide, or pass a number});
await manager.spawn();| Option | Type | Default | Description |
|---|---|---|---|
token | string | required | Your Discord bot token |
file | string | "./src/index.ts" | Entry point for each shard process |
totalShards | number | "auto" | "auto" | Number of shards to spawn |
All other options from discord.js ShardingManagerOptions are passed through.
Rolling restart
Section titled “Rolling restart”PopiiShardingManager supports zero-downtime rolling restarts — shards restart one at a time, so there’s always capacity while the update applies:
await manager.rollingRestart();To trigger a rolling restart from inside a shard (e.g. from a bot command):
// The shard sends a message to the managerprocess.send?.({ _popii_sharding_action: "rolling_restart" });Redis — required for cross-shard features
Section titled “Redis — required for cross-shard features”Several features only work across shards when Redis is connected:
| Feature | Requires Redis |
|---|---|
| Shared cooldowns | Yes |
pop.cooler persistence | Yes |
client.broadcast() cross-shard events | Yes |
presenceStrategy: "coordinated" | Yes |
Persistent pop.state | Yes |
Configure Redis in popiiClient():
const client = popiiClient({ token: process.env.DISCORD_TOKEN!, redisUrl: process.env.REDIS_URL,});Cross-shard messaging with broadcast
Section titled “Cross-shard messaging with broadcast”Emit an event on one shard and listen on all others:
// Emit from any shardawait pop.client.broadcast("cache-invalidate", { userId: pop.user.id });
// Listen on all shards (in a plugin's setup hook)client.onBroadcast("cache-invalidate", ({ userId }) => { userCache.delete(userId);});Under the hood, Popii uses Redis pub/sub when Redis is connected, or Discord.js IPC when it’s not. IPC is limited to shards on the same machine.
autoShard option reference
Section titled “autoShard option reference”| Option | Type | Default | Description |
|---|---|---|---|
token | string | required | Your Discord bot token |
file | string | "./src/index.ts" | Bot entry point |
threshold | number | 2500 | Guild count below which no ShardingManager is used |
totalShards | number | "auto" | Discord-recommended | Forwarded to PopiiShardingManager when sharding activates |
All other PopiiShardingOptions (which extend discord.js ShardingManagerOptions) are forwarded as-is.