What is Lavalink? Hosting a Discord music bot

Lavalink is a standalone audio server, built on Lavaplayer, that loads, decodes and sends music to Discord on behalf of your bot. The bot only sends commands.

Updated 5 min read

Learning objectives

After reading this article you will be able to:

  • Understand what Lavalink does and why music bots use it
  • Know how the bot, a client library and the Lavalink server connect
  • Set up application.yml and plan the hosting
On this page

Playing music in a Discord bot is harder than it looks. You have to fetch the track, decode the audio, encode it as Opus and push packets over a voice connection without stuttering. Doing that inside the bot itself eats CPU and memory, and any hiccup also slows down ordinary commands.

Lavalink fixes this by moving audio out of the bot. It is a separate program that does the heavy lifting, while the bot handles only commands and events.

User/playDiscordGatewayeventYour botLavalink clientcommandsand eventsLavalinkserveraudioVoice channelhears
The bot only sends commands; the Lavalink server loads the track and sends the audio straight to the voice channel.

Lavalink is a standalone audio-sending node built on the Lavaplayer library and the Koe project. It is open source, maintained at github.com/lavalink-devs/Lavalink. It runs as its own server, exposes a REST API and a WebSocket, and sends audio straight to Discord without that audio passing through your bot's shards.

It is not a bot and has no user-facing commands. It is a piece of infrastructure that your bot controls.

Three pieces talk to each other:

  1. The bot receives /play from a user.
  2. A client library inside the bot forwards the request to the Lavalink server and passes along the Discord voice connection data.
  3. The Lavalink server loads the track, applies filters, encodes the audio and sends it to the voice channel.

Bot and server exchange messages over HTTP (REST) and a WebSocket. The bot says "play this track", "pause", "change the volume" and receives events such as "the track ended". The audio never returns to the bot.

To authenticate, the client sends the configured password in the Authorization header. To check that the server is up, GET /version returns the version as plain text.

Lavalink makes sense when:

  • the bot plays music or audio from external sources;
  • the bot is in many servers and audio weighs on the main process;
  • you want to restart or update the bot without touching the audio service;
  • several bots or instances can share a few audio nodes.

It ships ready-made filters (equalizer, karaoke, timescale, tremolo, vibrato, rotation and more) and sources such as SoundCloud, Bandcamp, Twitch, Vimeo and HTTP links.

It is not worth it for a bot that plays one short file now and then, or one that does not use voice. It also does not settle copyright: it plays what the source delivers, and following each platform's terms remains the bot operator's job.

  • A Java LTS release. Check the minimum in the docs, which recommend the latest LTS release.
  • An application.yml file in the directory where you start it.
  • A password and a port (the official example uses 2333).
  • A client library compatible with Lavalink v4 in your bot.

A minimal application.yml:

yaml
server:
  port: 2333
  address: 0.0.0.0
lavalink:
  server:
    password: "change-this-password"
    sources:
      youtube: false
      soundcloud: true
  plugins:
    - dependency: "dev.lavalink.youtube:youtube-plugin:VERSION"
      snapshot: false

Replace VERSION with the current version on the Releases tab of youtube-source. The official example ships the password youshallnotpass: never keep it in production.

To run it, the docs list the standalone binary (java -jar Lavalink.jar), systemd on Linux, or Docker. With Docker, the official image is ghcr.io/lavalink-devs/lavalink:4, with your file mounted at /opt/Lavalink/application.yml.

Each language has community-maintained clients, listed at lavalink.dev/clients: Shoukaku, Riffy and Moonlink.js for JavaScript; Wavelink and Mafic for Python; Lavalink-Client for the JVM. Wavelink 3, for example, works with Lavalink v4; check PyPI for the minimum Python version. A skeleton with discord.py and Wavelink 3 (pip install -U wavelink):

python
import os
import discord
import wavelink
from discord.ext import commands

class Bot(commands.Bot):
    async def setup_hook(self):
        node = wavelink.Node(
            uri=os.environ["LAVALINK_URI"],  # e.g. http://localhost:2333
            password=os.environ["LAVALINK_PASSWORD"],
        )
        await wavelink.Pool.connect(nodes=[node], client=self)

intents = discord.Intents.default()
intents.message_content = True
bot = Bot(command_prefix="!", intents=intents)

@bot.command()
async def play(ctx, *, query: str):
    if not ctx.author.voice:
        return await ctx.send("Join a voice channel first.")
    player = ctx.voice_client or await ctx.author.voice.channel.connect(cls=wavelink.Player)
    tracks = await wavelink.Playable.search(query)
    if tracks:
        await player.play(tracks[0])

bot.run(os.environ["DISCORD_TOKEN"])

Keep the URI, password and token in environment variables, never in code. If you do not have a bot yet, start with how to make a Discord bot.

The YouTube support that used to be built into the server is deprecated and ships disabled in the example application.yml. The recommended route is the youtube-source plugin, which requires turning off the built-in source (youtube: false) and declaring the plugin, as in the example above.

Because it is a plugin, it evolves separately from the server and may need an update when YouTube changes something. If music suddenly stopped, check the logs and the plugin version first, and see why a music bot stopped playing YouTube.

Lavalink is a Java process that must stay on all the time: if it goes down, every track stops. Plan for four things:

  • Continuous uptime. The same reasoning as keeping a Discord bot online 24/7 applies to the audio node.
  • Memory. The JVM accepts a heap cap through JAVA_TOOL_OPTIONS=-Xmx.... Measure real usage with a few tracks playing at once before you settle on a value, and see how much RAM a Discord bot needs.
  • Latency. The closer Lavalink sits to the bot, the better.
  • Security. Use a strong password and do not expose the port unnecessarily: anyone with the password controls your node.

How to do this on Square Cloud#

On Square Cloud, the bot and the audio node become two applications in the same account: Lavalink runs as a web application (from 512 MB), and you restart either one without taking down the other. In application.yml, use port: ${PORT} to listen on the port the platform sets; the bot connects to the application's subdomain on port 443 over a secure connection (secure: true, or an https:// URI in Wavelink). The platform's Java runtime runs the server; check that its Java version meets the minimum Lavalink requires.

You deploy by ZIP upload in the dashboard, the CLI, GitHub or the VS Code extension. The squarecloud.app config file is optional: the dashboard generates runtime, memory and main file at deploy time, and writing the file at the project root is the alternative. Your plan's RAM is a pool shared across your applications, with a minimum of 256 MB per background application such as the bot. Containers are always on, automatic restart is on by default when you deploy from the dashboard and brings the process back when it exits with an error, and logs show in real time in the dashboard.

Your Discord bot can use discord.js, discord.py, JDA and other libraries, with sharding and voice, and the average latency to the Discord Gateway is about 30 ms. See the details in Discord bot hosting.

Bot hosting

Keep your bot online 24/7 with automatic restarts

Learn more

FAQs

Is Lavalink a bot?

No. Lavalink is an audio server. What joins Discord and answers commands is still your bot, which uses a client library to talk to Lavalink.

Do I need Java to use Lavalink?

Yes, for the server: Lavalink runs on the JVM, and the official docs list the minimum Java version. Your bot itself can be written in another language, such as Python or JavaScript.

Can I run Lavalink in the same place as my bot?

You can, but it is a separate Java process. Many people run the two as separate applications so one can restart without taking down the other.

Why won't my Lavalink play YouTube?

The YouTube support built into the server is deprecated and ships disabled in the example application.yml. YouTube goes through a separate plugin, youtube-source; without it, YouTube links and searches usually fail.

Next articleHow much RAM does a Discord bot need?A small Discord bot runs fine on 256 to 512 MB of RAM. See what makes memory grow, how to measure your bot and how to trim the cache.