Gateway and sharding

Shard is one websocket connection; ShardManager coordinates the shards in a process. Below roughly 2,500 guilds you can rely on defaults.

Shard is one websocket connection; ShardManager coordinates the shards in a process. Below roughly 2,500 guilds you can rely on defaults.

Startup sequence

  1. connect() reads the recommended shard count and session limits from Discord.
  2. With maxShards: 'auto' that count is used; shardConcurrency: 'auto' uses Discord's max_concurrency.
  3. Each shard opens its socket, gets HELLO, sends IDENTIFY, then receives READY and a burst of GUILD_CREATE.
  4. After guildCreateTimeout, the shard fires shardReady. When all shards are ready, the client emits ready.

Sharding modes

Single process, auto:

new Client(token, { maxShards: 'auto', shardConcurrency: 'auto' });

Multi-process, contiguous ranges (total must match across processes, since Discord routes by guild_id % total):

new Client(token, { maxShards: 16, firstShardID: 0, lastShardID: 7 });   // process A
new Client(token, { maxShards: 16, firstShardID: 8, lastShardID: 15 });  // process B

Explicit IDs:

new Client(token, { maxShards: 16, shards: [0, 2, 4, 6, 8, 10, 12, 14] });

Connection concurrency

Shards sharing id % max_concurrency are in the same identify bucket. Athena waits for a free bucket, then enforces a 5 second cooldown before the next identify in that bucket (skipped for resumes). max_concurrency comes from Discord and rises with scale; very large bots request elevated access.

Heartbeats, reconnect, resume

Athena heartbeats at Discord's interval and tears the socket down if an ACK is missed (zombie connection). On disconnect, if a session ID is held it issues RESUME to replay missed events; if the session expired or maxResumeAttempts is exceeded it re-identifies. Reconnect delay follows reconnectDelay(lastDelay, attempts).

Member chunking

For many members on one guild, Discord requires the gateway, not REST:

const members = await shard.requestGuildMembers({ guild_id: guildID, query: '', limit: 0 });

This now waits the configured request timeout for the chunks (rather than returning early). getAllUsers: true chunks every guild at startup and significantly delays ready on large bots.

Presence and voice

shard.setPresence(PresenceUpdateStatus.DoNotDisturb, [{ name: 'with code', type: ActivityType.Playing }]);
shard.sendWS(GatewayOpcodes.VoiceStateUpdate, { guild_id, channel_id, self_mute: false, self_deaf: false });

Athena does not bundle a voice-connection (audio) implementation; pair it with a dedicated voice library if you need audio.

Useful shard surface

shard.status;     // 'disconnected' | 'connecting' | 'handshaking' | 'ready' | ...
shard.latency;    // ms
shard.sessionID;
shard.connect(); shard.disconnect({ reconnect: true });
shard.requestGuildMembers(options);

Tuning

  • Default to maxShards: 'auto'.
  • Keep compress on (zlib-stream cuts gateway bandwidth a lot).
  • Use disableEvents for noisy events you ignore.
  • Stagger reconnects with a randomised reconnectDelay to avoid thundering herds after an outage.

For the cluster + cache picture at the very top end, see Scaling to millions.