Guides

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.

node-selection.ts
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.

node-move.ts
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.

track-decoding.ts
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.

rest-operations.ts
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 catch NodeManagerError if no node may be up.
  • Always check node.ready before forcing node-specific operations.
  • Use node.rest only for low-level operations; prefer manager/player abstractions for typical flows.
  • node.isNodelink() tells you the node is a fork, which skips plugin validation.