Recipes

Understanding sharding

Sharding

By default, seyfert does sharding internally

This section tries to explain other methods and how to do it manually and/or with further optimizations.

In seyfert the sharding approach is to give the full benefit of scaling while keeping the same structure in your project.

Why sharding?

JavaScript runtimes are single-threaded, which means that without sharding, all processing would happen in a single thread. This creates a processing limit where all the load is evaluated together. Seyfert handles sharding internally in the Client instance to help distribute this load across multiple processes or threads (although it is still an imperfect technique).

Managing shards

The base of the Worker is to allow to execute code in parallel in different parts of the CPU, either in threads or different processes. In terms of discord, this means the ability to connect several shards by spreading the load on each Worker, for seyfert this is just changing the mode property in the WorkerManager to decide the execution mode between threads to spawn clients on processor threads or clusters to spawn clients on different processes of the runtime.

import { WorkerManager } from 'seyfert';

const manager = new WorkerManager({
	mode: "threads",
	// ./src/client.ts for bun and deno (?
	path: "./dist/client.js",
	// you can override a lot of options, like number of workers, shards per worker...
});

manager.start();
import { ParseClient, WorkerClient } from "seyfert";

const client = new WorkerClient();

client.start();

declare module 'seyfert' {
	interface SeyfertRegistry { client: ParseClient<WorkerClient> }
}

Seyfert handles the sharding logic for you, so switching execution modes is just changing the mode property shown above.

Scaling workers across hosts

threads and clusters distribute workers inside one machine. When the same gateway topology must run across several VPSs or hosts, @slipher/scaler (WIP) connects agents to one master, places logical workers by capacity, and redistributes them live when hosts join or leave.

The scaler keeps each logical worker's shard range stable while moving its physical process. This is separate from changing the total number of Discord shards.

Cache

Unlike traditional Discord libraries, Seyfert offers unified cache management across all shards. The cache can be centralized in the main process (the WorkerManager executor), ensuring consistent data access throughout your application.

To implement centralized caching, use the WorkerAdapter:

import { WorkerClient, WorkerAdapter } from 'seyfert';

const client = new WorkerClient();

client.setServices({
	cache: {
		adapter: new WorkerAdapter(client.workerData)
	}
});

await client.start();

Accessing shards at runtime

The gateway exposes a few helpers to inspect shards while your bot is running:

// Average gateway latency
client.gateway.latency;

// Per-shard ping
await client.gateway.get(ctx.shardId)?.ping();

// Total shard count
client.gateway.totalShards;

// Calculate shard for a guild
client.gateway.calculateShardId('guildId');

Talking to other workers

If for some reason (I did not find any for the example), you want a specific worker to execute an action that another one received, you can simply ask it.

client.tellWorker(
	1,
	(worker, vars) => console.log(`Hii worker #${worker.workerId} from ${vars.workerId}`),
	{ workerId: client.workerId }
);