Every Discord music bot hits the same wall: the free public Lavalink node it relies on is overloaded, rate-limited by YouTube, or simply gone. Your bot joins the voice channel and plays nothing.
Running your own Lavalink server 24/7 fixes that. This guide deploys Lavalink v4 in one click, then connects a discord.js bot to it.
What Lavalink does
Lavalink is a standalone Java server that does the heavy part of a music bot: searching tracks, downloading and decoding audio, and streaming it to Discord’s voice servers. Your bot only sends commands (“play this in that channel”) over a WebSocket.
That split is why a music bot stays light: the bot itself can run in 256 MB, while Lavalink, being Java, wants more memory. Plan for at least 512 MB for a small node, 1 GB if it plays in many servers at once.
Step 1: deploy the Lavalink server
Sign in to Bot-Hosting.net and start a new deployment:
- What are you deploying? Choose Service.
- Pick Lavalink (“Audio node for Discord music bots”).
- Give it the RAM you planned, then launch.
You get Lavalink 4 on Java 21, ready to play, with:
- the YouTube plugin installed, since the YouTube source built into Lavalink is deprecated and disabled;
- SoundCloud and Bandcamp enabled;
- an
application.ymlyou can edit in the Files tab; - a generated password in the
LAVALINK_SERVER_PASSWORDenvironment variable, managed by the platform.
Start it and watch the Console. Lavalink is ready when it prints:
Lavalink is ready to accept connections. Step 2: find the host, port and password
Your bot needs three values:
| Value | Where to find it |
|---|---|
| Host | Network tab, the node’s host or IP |
| Port | Network tab, the primary port (also SERVER_PORT) |
| Password | Environment tab, LAVALINK_SERVER_PASSWORD |
The copy button next to the primary port in the Network tab copies host:port in one go. The password is a secret, locked System variable: use its copy button in the Environment tab rather than retyping it.
Step 3: connect a discord.js bot with Shoukaku
Shoukaku is a widely used Lavalink v4 client for discord.js. In your bot’s deployment, add three environment variables, LAVALINK_HOST, LAVALINK_PORT and LAVALINK_PASSWORD (secret), then:
const { Client, GatewayIntentBits } = require('discord.js');
const { Shoukaku, Connectors } = require('shoukaku');
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates]
});
const shoukaku = new Shoukaku(new Connectors.DiscordJS(client), [
{
name: 'main',
url: `${process.env.LAVALINK_HOST}:${process.env.LAVALINK_PORT}`,
auth: process.env.LAVALINK_PASSWORD
}
]);
shoukaku.on('ready', (name) => console.log(`Lavalink node ${name} connected`));
shoukaku.on('error', (name, error) => console.error(`Lavalink node ${name}:`, error));
client.login(process.env.DISCORD_TOKEN); Two things often forgotten:
GuildVoiceStatesis required. Without it, the bot never learns which voice server to stream to, and joins channels in silence.- Create the Shoukaku instance before
login(), so it catches the ready event.
To play a track, search it on the node and send it to a player:
const node = shoukaku.options.nodeResolver(shoukaku.nodes);
const result = await node.rest.resolve('ytsearch:never gonna give you up');
if (result?.loadType !== 'search' || !result.data.length) return;
const player = await shoukaku.joinVoiceChannel({
guildId: interaction.guildId,
channelId: interaction.member.voice.channelId,
shardId: 0
});
await player.playTrack({ track: { encoded: result.data[0].encoded } }); If YouTube searches fail, try scsearch: (SoundCloud) to check that the node itself works.
Python bots connect the same way with wavelink: wavelink.Node(uri=f"http://{host}:{port}", password=password).
Keeping the node healthy
- YouTube changes often. When searches start failing, update the YouTube plugin version in
application.ymland restart. Many “no matches” or “this video is unavailable” waves are fixed by a newer plugin release. YouTube also blocks some datacenter IPs; the comment inapplication.ymlpoints to the plugin’s OAuth option for that case. - Watch memory. If the Console says the app was killed for using more memory than it has, give the deployment more RAM.
- Keep the password private. Anyone who has it, plus the address, can use your node.
- One node per bot is enough until you play in hundreds of channels at once.
What it costs
Lavalink plus the bot means two deployments and around 768 MB of RAM in total, so it fits on a paid plan rather than the free one (256 MB, one slot, renewed by hand every 4 days). Plans share one pool of RAM across all your deployments: Starter has 1 GB and 2 slots, exactly the size of a bot and its Lavalink node. See pricing.
Skip the code: a full music bot
The Music Bot (Lavalink) template is a complete discord.js music bot, with queue, loop, filters, lyrics, playlists, radio and 70+ slash commands, made to pair with the one-click Lavalink above.