Node Management
Select nodes, check health, and perform low-level node operations.
This guide covers node selection strategies, health checks, and operations like decode and REST calls.
Select Nodes
getLeastUsed() picks among the connected nodes and throws a NodeManagerError when there are
none — it never returns undefined.
import { } from 'hoshimi';
import type { } from 'hoshimi';
declare const : ;
const = ..(); // default
const = ..(.);
const = ..(() => .?. ?? 0);
.(`Using node: ${.}`);
.(`Ready: ${.}`);
.(`Penalties: ${.}`);
.(., .);Sort strategies: Penalties (default), Players, PlayingPlayers, Cpu, SystemLoad,
LavalinkLoad, Memory — or any function returning a number, where lowest wins. Penalties combine the
player count with CPU load and frame deficits.
Moving players between nodes
player.move() re-creates the player on another node, keeping position, volume and filters. It refuses
the move when the target lacks a source manager the queue depends on, so a Spotify queue never lands on a
node that cannot play it.
import type { , } from 'hoshimi';
declare const : ;
declare const : ;
await .(..());Set nodeOptions.moveOptions.move to have Hoshimi do this automatically for every player of a node that
disconnects, picking the target with moveOptions.filterBy.
Decode Tracks
Decode Lavalink track data to extract metadata.
import type { } from 'hoshimi';
declare const : ;
const = await ..('QAAAyAIA...', 'user-id');
const = await ..(['QAAAyAIA...', 'QAAByAIA...'], 'user-id');
.(..);
.(.);REST Operations
Access low-level REST endpoints for advanced use cases.
import type { } from 'hoshimi';
declare const : ;
const = await ..();
.(`Active players: ${.}`);Staying connected
Each socket runs a ping/pong heartbeat: if a ping goes unanswered within
nodeOptions.heartbeatOptions.interval (30s by default), the socket is terminated and the normal
reconnect path takes over. Set it to 0 to disable.
A dropped node retries retryAmount times, retryDelay apart, then destroys itself and emits
NodeError. sessionOptions.resumable keeps the node's Lavalink session alive for timeout seconds
across a socket drop; byLibrary is the complementary fallback for when the node returns on a fresh
session, replaying the players Hoshimi still holds in memory. They stack — they are not alternatives.
For the full resume story — Lavalink's own session resume, byLibrary, a custom resumeFn, and
rebuilding queues from storage — see the Resume sessions after a restart recipe.
Best Practices
- Prefer
getLeastUsed()for default load balancing, and catchNodeManagerErrorif no node may be up. - Always check
node.readybefore forcing node-specific operations. - Use
node.restonly for low-level operations; prefer manager/player abstractions for typical flows. node.isNodelink()tells you the node is a fork, which skips plugin validation.