Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/disgoorg/disgo/llms.txt

Use this file to discover all available pages before exploring further.

The sharding package manages multiple gateway connections for bots in many guilds. Discord requires sharding for bots in 2,500+ guilds.

Overview

Sharding distributes guilds across multiple gateway connections, each identified by a shard ID. The shard manager handles:
  • Opening and closing shards
  • Distributing guilds to shards using Discord’s formula
  • Rate limiting IDENTIFY requests
  • Automatic re-sharding when required
  • Resuming shards with saved session state

Core types

ShardManager

Manages multiple gateway connections.
type ShardManager interface {
    Open(ctx context.Context)
    Close(ctx context.Context)
    OpenShard(ctx context.Context, shardID int) error
    ResumeShard(ctx context.Context, shardID int, state ShardState) error
    CloseShard(ctx context.Context, shardID int)
    ShardByGuildID(guildID snowflake.ID) gateway.Gateway
    Shard(shardID int) gateway.Gateway
    Shards() iter.Seq[gateway.Gateway]
}

Methods

Open(ctx)
void
Opens all configured shards concurrently
Close(ctx)
void
Closes all shards concurrently
OpenShard(ctx, shardID)
error
Opens a specific shard by ID
ResumeShard(ctx, shardID, state)
error
Resumes a specific shard with saved session state
CloseShard(ctx, shardID)
void
Closes a specific shard by ID
ShardByGuildID(guildID)
gateway.Gateway
Returns the shard that manages the specified guild
Shard(shardID)
gateway.Gateway
Returns the gateway for the specified shard ID
Shards()
iter.Seq[gateway.Gateway]
Returns an iterator over all active shards

ShardState

Session state for resuming a shard.
type ShardState struct {
    SessionID string
    Sequence  int
    ResumeURL string
}
SessionID
string
The session ID from the gateway READY event
Sequence
int
The last sequence number received from the gateway
ResumeURL
string
The resume URL from the gateway READY event

Creating a shard manager

New

Creates a new shard manager.
func New(
    token string,
    eventHandlerFunc gateway.EventHandlerFunc,
    opts ...ConfigOpt,
) ShardManager
token
string
The bot token
eventHandlerFunc
gateway.EventHandlerFunc
The function to handle gateway events from all shards
opts
...ConfigOpt
Configuration options

Configuration options

WithLogger

Sets the logger for the shard manager.
func WithLogger(logger *slog.Logger) ConfigOpt

WithShardIDs

Specifies which shard IDs to manage.
func WithShardIDs(shardIDs ...int) ConfigOpt
shardIDs
...int
The shard IDs to manage (e.g., 0, 1, 2 for managing shards 0-2)
Note: Use this for stateless sharding or when managing a subset of shards.

WithShardIDsWithStates

Specifies shard IDs with session states for resuming.
func WithShardIDsWithStates(shards map[int]ShardState) ConfigOpt
shards
map[int]ShardState
Map of shard ID to session state for resuming

WithShardCount

Sets the total number of shards.
func WithShardCount(shardCount int) ConfigOpt
shardCount
int
Total number of shards. Leave at 0 to let Discord determine the count

WithShardSplitCount

Sets how many shards a shard should split into when auto-scaling.
func WithShardSplitCount(shardSplitCount int) ConfigOpt
shardSplitCount
int
Number of new shards to create from one shard. Default is 2

WithAutoScaling

Enables automatic re-sharding when Discord requires it.
func WithAutoScaling(autoScaling bool) ConfigOpt
autoScaling
bool
Whether to automatically re-shard when required. Default is false
Note: When enabled and Discord sends a “sharding required” close code, the manager automatically splits the shard according to ShardSplitCount.

WithGatewayCreateFunc

Sets a custom gateway creation function.
func WithGatewayCreateFunc(gatewayCreateFunc gateway.CreateFunc) ConfigOpt

WithGatewayConfigOpts

Applies configuration options to all created gateways.
func WithGatewayConfigOpts(opts ...gateway.ConfigOpt) ConfigOpt
opts
...gateway.ConfigOpt
Gateway configuration options applied to all shards

WithIdentifyRateLimiter

Sets a custom rate limiter for IDENTIFY requests.
func WithIdentifyRateLimiter(rateLimiter gateway.IdentifyRateLimiter) ConfigOpt

WithIdentifyRateLimiterConfigOpt

Configures the default identify rate limiter.
func WithIdentifyRateLimiterConfigOpt(opts ...gateway.IdentifyRateLimiterConfigOpt) ConfigOpt

WithCloseHandler

Sets a handler called when a shard closes.
func WithCloseHandler(closeHandler gateway.CloseHandlerFunc) ConfigOpt
closeHandler
gateway.CloseHandlerFunc
Function called when a shard closes and cannot reconnect
Note: Not called when auto-scaling triggers a re-shard.

Utility functions

ShardIDByGuild

Calculates which shard manages a specific guild.
func ShardIDByGuild(guildID snowflake.ID, shardCount int) int
guildID
snowflake.ID
The guild ID
shardCount
int
The total number of shards
Returns: The shard ID that should manage this guild. Formula: (guildID >> 22) % shardCount

Usage examples

Basic sharding

package main

import (
    "context"
    "github.com/disgoorg/disgo/sharding"
    "github.com/disgoorg/disgo/gateway"
)

func main() {
    // Create shard manager
    manager := sharding.New(
        token,
        func(event gateway.EventData) {
            // Handle events from all shards
        },
        sharding.WithShardCount(4), // 4 shards
        sharding.WithShardIDs(0, 1, 2, 3), // Manage all 4
    )
    
    // Open all shards
    manager.Open(context.Background())
    defer manager.Close(context.Background())
    
    // Get shard for a specific guild
    shard := manager.ShardByGuildID(guildID)
    latency := shard.Latency()
}

Auto-scaling

manager := sharding.New(
    token,
    eventHandler,
    sharding.WithAutoScaling(true),
    sharding.WithShardSplitCount(2), // Split into 2 when needed
    sharding.WithShardCount(2), // Start with 2 shards
)

// When Discord requires more shards:
// - Shard 0 will automatically split into shards 0 and 2
// - Shard 1 will automatically split into shards 1 and 3
// - New total: 4 shards

Resuming shards

// Save shard states when shutting down
states := make(map[int]sharding.ShardState)
for shard := range manager.Shards() {
    states[shard.ShardID()] = sharding.ShardState{
        SessionID: shard.SessionID(),
        Sequence:  shard.Sequence(),
        ResumeURL: shard.ResumeURL(),
    }
}
// Save states to database/file

// Resume with saved states
manager := sharding.New(
    token,
    eventHandler,
    sharding.WithShardIDsWithStates(states),
    sharding.WithShardCount(len(states)),
)
manager.Open(context.Background())

Stateless sharding

For distributed setups where different processes handle different shards:
// Process 1: Handles shards 0-1
manager1 := sharding.New(
    token,
    eventHandler,
    sharding.WithShardIDs(0, 1),
    sharding.WithShardCount(4), // Total across all processes
)

// Process 2: Handles shards 2-3
manager2 := sharding.New(
    token,
    eventHandler,
    sharding.WithShardIDs(2, 3),
    sharding.WithShardCount(4),
)

Custom gateway configuration

manager := sharding.New(
    token,
    eventHandler,
    sharding.WithGatewayConfigOpts(
        gateway.WithCompress(true),
        gateway.WithIntents(
            gateway.IntentGuilds,
            gateway.IntentGuildMessages,
        ),
        gateway.WithPresenceOpts(
            gateway.WithWatchingActivity("the shards"),
            gateway.WithOnlineStatus(discord.OnlineStatusDND),
        ),
    ),
)

Monitoring shards

// Iterate over all shards
for shard := range manager.Shards() {
    fmt.Printf("Shard %d: Latency=%v, Status=%s\n",
        shard.ShardID(),
        shard.Latency(),
        shard.Status(),
    )
}

// Get specific shard
if shard := manager.Shard(0); shard != nil {
    latency := shard.Latency()
}

// Find shard for a guild
shard := manager.ShardByGuildID(guildID)

Close handler

manager := sharding.New(
    token,
    eventHandler,
    sharding.WithCloseHandler(func(
        shard gateway.Gateway,
        err error,
        reconnect bool,
    ) {
        log.Printf("Shard %d closed: %v (reconnect=%v)",
            shard.ShardID(),
            err,
            reconnect,
        )
        
        // Save shard state for resuming
        if reconnect {
            saveShardState(sharding.ShardState{
                SessionID: shard.SessionID(),
                Sequence:  shard.Sequence(),
                ResumeURL: shard.ResumeURL(),
            })
        }
    }),
)

Best practices

  1. Start with auto-determined shard count: Let Discord determine the optimal shard count initially
  2. Enable auto-scaling: For large bots that may grow, enable auto-scaling to handle re-sharding automatically
  3. Save session states: Always save session IDs, sequences, and resume URLs to resume shards after restarts
  4. Monitor shard health: Track latency and connection status for each shard
  5. Use stateless sharding for scale: Distribute shards across multiple processes/servers for horizontal scaling
  6. Configure rate limiting: Adjust identify rate limiter settings based on your bot’s verification status

Build docs developers (and LLMs) love