RE:NODE

Minecraft13 min read

BungeeCord vs Velocity: Minecraft proxies

BungeeCord and Velocity compared: forwarding security, plugin support, performance and config, plus a step-by-step migration from BungeeCord to Velocity.

0 readers

For a new Minecraft network, use Velocity. It is the proxy PaperMC maintains and recommends, its modern forwarding mode protects your backends without extra plugins, and it handles more players per core than BungeeCord. BungeeCord is still maintained and still runs a large share of the world's networks, and there is exactly one good reason to stay on it: a plugin you depend on that has no Velocity build. If that is not you, the migration is an afternoon - a new config file, one setting per backend, and a plugin audit - and this post walks through it, along with the honest differences between the two.

The full Velocity setup - every line of velocity.toml, shared permissions, forced hosts - is in the Velocity network guide. This post is the comparison and the move.

What both proxies do, and where they differ#

Both are the same kind of program. A player connects to the proxy, the proxy authenticates them against Mojang once, then opens its own connection to a backend server and relays packets in both directions. Moving between servers is the proxy closing one backend connection and opening another while the player's connection stays up. Neither proxy simulates anything: there are no worlds, no blocks and no entities on a proxy, which is why it needs very little memory.

The differences are in four places:

BungeeCordVelocity
Maintainermd_5 (SpigotMC)PaperMC
Configconfig.yml (YAML)velocity.toml (TOML)
Identity forwardingUnsigned (ip_forward)Signed (modern), or legacy modes
Backend protectionFirewall or BungeeGuardBuilt in with modern forwarding
Plugin APIBungeeCord APIVelocity API
Backend versionsAnyModern forwarding needs 1.13+

Forwarding is the difference that matters most and the one people understand least. It is covered in its own section below, because it decides whether your backends can be joined directly by anyone who finds their port.

Plugin APIs are not compatible. A BungeeCord plugin does not load on Velocity, a Velocity plugin does not load on BungeeCord, and Paper plugins load on neither. Most large network plugins - LuckPerms, Geyser and Floodgate, ViaVersion, the major chat and ban plugins - publish builds for both. Small or abandoned plugins often exist only for BungeeCord, which has been around since 2013.

Performance favours Velocity. It was written from scratch around Netty with native compression and encryption libraries on Linux, and it does less work per packet. In practice that rarely matters below a few hundred concurrent players, where either proxy idles on a fraction of a core. It starts to matter on large networks, and on hosts where each process has a hard CPU limit.

Configuration is mostly a translation exercise. The concepts - listeners, a server list, a try order, forced hosts, a compression threshold - exist in both under different names.

Waterfall is finished, and what that means for you#

Waterfall was PaperMC's fork of BungeeCord, with performance fixes and extra configuration on top. Many networks that think of themselves as "on BungeeCord" are actually on Waterfall. PaperMC ended Waterfall development and points everyone at Velocity. It still runs, but it receives no updates, which means no support for new Minecraft protocol versions and no security fixes.

If you are on Waterfall today you have two choices: move back to upstream BungeeCord, which reads almost the same config.yml and runs the same plugins, or move to Velocity. Going back to BungeeCord is the smaller step; going to Velocity is the one you will not have to repeat. If you are going to touch every backend anyway, do it once.

Forwarding: the security difference#

When a player connects through a proxy, the backend sees a connection from the proxy's address, not from the player. Without help, every player would arrive with the proxy's IP and an offline-mode UUID, which breaks bans, skins and every plugin that stores data by UUID. Forwarding is how the proxy tells the backend who the player really is.

BungeeCord's ip_forward

BungeeCord does this by appending the player's real address, UUID and profile properties to the handshake. You switch it on with ip_forward: true in the proxy's config.yml and settings.bungeecord: true in each backend's spigot.yml.

The problem is that the backend has no way to check that the data came from your proxy. It trusts whatever the handshake says. Because backends run with online-mode=false (the proxy did the authentication), anyone who can reach a backend's port directly can send a crafted handshake claiming to be any player, including an operator, and the backend lets them in. This is not a theoretical weakness; there are public tools that do exactly this, and open BungeeCord backends are found by scanners within hours.

The two fixes are a firewall that only lets the proxy reach the backends, or BungeeGuard, a plugin pair that adds a secret token to the forwarded data so backends can reject connections without it. On a machine you control, the firewall is the stronger option. On a shared panel host, where every server is a separate container with its own public port, you usually cannot firewall your own backends from the internet, and BungeeGuard is not optional.

Velocity's modern forwarding

Velocity's modern mode sends the same identity data inside a payload signed with a secret shared between the proxy and each backend. Paper verifies the signature and refuses anything without a valid one, before login completes. A player who finds a backend's address and connects directly gets kicked. No firewall and no extra plugin.

The cost is compatibility: modern forwarding needs a backend that understands it, which means Paper 1.13 or newer, or a Fabric or NeoForge backend with a proxy-compatibility mod. For older backends Velocity offers legacy (BungeeCord-style, with the same weakness) and bungeeguard (legacy plus a BungeeGuard token).

Velocity modeEquivalent toBackend needs
noneNo forwardingNothing - players get offline UUIDs
legacyBungeeCord ip_forwardbungeecord: true in spigot.yml and a firewall
bungeeguardBungeeCord plus BungeeGuardBungeeGuard plugin on the backend
modernNothing on BungeeCordPaper 1.13+ with Velocity support enabled

The configs side by side#

A typical BungeeCord config.yml, trimmed to the parts that carry over:

BungeeCord config.yml
online_mode: trueip_forward: truenetwork_compression_threshold: 256connection_throttle: 4000player_limit: -1listeners:- host: 0.0.0.0:25565  motd: '&bThe Longhouse Network'  max_players: 200  force_default_server: true  priorities:  - lobby  forced_hosts:    survival.example.com: survival  ping_passthrough: false  query_enabled: falseservers:  lobby:    address: 10.0.0.11:25566    restricted: false    motd: 'Lobby'  survival:    address: 10.0.0.12:25567    restricted: false    motd: 'Survival'

And the same network in velocity.toml:

velocity.toml
bind = "0.0.0.0:25565"motd = "<aqua>The Longhouse Network"show-max-players = 200online-mode = trueplayer-info-forwarding-mode = "modern"forwarding-secret-file = "forwarding.secret"[servers]lobby = "10.0.0.11:25566"survival = "10.0.0.12:25567"try = ["lobby"][forced-hosts]"survival.example.com" = ["survival"][advanced]compression-threshold = 256login-ratelimit = 3000

How the keys map:

BungeeCordVelocityNotes
listeners[].hostbindVelocity has one listener
listeners[].prioritiesservers.tryOrder matters in both
listeners[].forced_hosts[forced-hosts]Velocity takes a list per host
listeners[].motdmotdLegacy & codes become MiniMessage
ip_forwardplayer-info-forwarding-modeSee the forwarding table
network_compression_thresholdcompression-thresholdSame meaning
connection_throttlelogin-ratelimitMilliseconds between logins per IP
servers.<name>.restrictedNo direct keyUse permissions on /server instead
groups / permissionsNo built-in systemUse LuckPerms on the proxy

Two behaviours differ in ways that surprise people. First, force_default_server: true on BungeeCord sends every player to the first priority server on each login; Velocity always uses the try list on initial connection and does not remember the last server unless a plugin does it. Second, BungeeCord ships with a basic permission system in config.yml (the groups and permissions blocks, with md_5 as an example admin). Velocity has none: without a permissions plugin, only the console has access to admin commands. Install LuckPerms on the proxy as part of the migration rather than after it.

Migrating from BungeeCord to Velocity, step by step#

Plan for a short downtime window. The backends need one setting changed and a restart, and they cannot accept both kinds of forwarding at once.

  1. Audit your proxy plugins. List every jar in BungeeCord's plugins folder and find the Velocity build of each. Where there is none, find a replacement or decide you can live without it. Do this first; it is the step that can stop the migration.
  2. Check backend versions and software. Modern forwarding needs Paper 1.13 or newer. Spigot backends should move to Paper - it reads the same worlds and runs the same plugins. Anything older than 1.13 stays on legacy or bungeeguard forwarding.
  3. Install Velocity beside BungeeCord. Put velocity.jar in a new directory, run it once to generate velocity.toml and forwarding.secret, then stop it.
  4. Translate the config using the mapping table above. Keep BungeeCord's server names: plugins on the backends that send players by name (lobby, survival) keep working if the names do not change.
  5. Install the proxy plugins you found in step 1, starting with LuckPerms. If LuckPerms already used a shared database on BungeeCord, point the Velocity copy at the same database and everything carries over.
  6. Stop the network. Stop BungeeCord, then each backend.
  7. Switch each backend. In spigot.yml set settings.bungeecord: false. In config/paper-global.yml set the Velocity block and paste the secret. Remove BungeeGuard from the backend if it was installed.
  8. Start Velocity on the public port, then the backends. Watch the Velocity console for the forwarding error described in the troubleshooting section.
  9. Test direct connections to every backend and confirm they are refused.
  10. Keep BungeeCord's directory untouched for a week. Rolling back is reversing step 7 and starting the old jar.

The backend change in step 7 looks like this:

spigot.yml (backend)
settings:  bungeecord: false
config/paper-global.yml (backend)
proxies:  bungee-cord:    online-mode: true  velocity:    enabled: true    online-mode: true    secret: 'paste-the-contents-of-forwarding.secret'

On Paper versions before 1.19, these settings lived in paper.yml rather than config/paper-global.yml, under settings.velocity-support. If your backends are that old, check the file you actually have before editing a path from a guide.

Plugin messaging and backend plugins#

Many backend plugins talk to the proxy through the BungeeCord plugin messaging channel: selector menus that send players to a server, signs that show player counts, minigame plugins that return players to the lobby. They were written for BungeeCord, and they keep working on Velocity because Velocity implements that channel. In velocity.toml it is bungee-plugin-message-channel = true under [advanced], on by default.

What does not carry over is anything that relied on a BungeeCord plugin being present on the proxy. If a backend plugin expects a companion proxy plugin, that companion needs a Velocity build too. Read each plugin's page for "Velocity support" before the migration night, not during it.

Version translation is the other common dependency. A BungeeCord network that accepts several client versions usually runs ViaVersion (and sometimes ViaBackwards and ViaRewind) on the proxy or the backends. ViaVersion publishes a Velocity build, and it can equally live on each Paper backend; where you put it is a matter of preference, as long as it is not in both places.

Bedrock players through Geyser and Floodgate work on either proxy. On Velocity, put Geyser and Floodgate on the proxy and Floodgate on each backend too, with the same key.pem, so the backends recognise Floodgate players - the Geyser guide has the details.

Commands and administration#

The admin commands overlap but are not identical, which matters for staff habits and for any scripts or Discord bots that send commands to the proxy console.

TaskBungeeCordVelocity
Move yourself/server <name>/server <name>
Players per server/glist/glist
Move another player/send <player> <server>/send <player> <server>
Network broadcast/alert <message>Needs a plugin
Find a player/find <player>Needs a plugin
Reload config/greload (unreliable)/velocity reload
Stop the proxyendshutdown
Version/bungee/velocity info

/velocity reload is genuinely useful: it picks up added and removed servers in velocity.toml without kicking anyone. BungeeCord's reload has never been trustworthy, and most BungeeCord admins restart the proxy instead, which disconnects the whole network.

Velocity's commands each have a permission node (velocity.command.server, velocity.command.glist, velocity.command.send), so you grant them through LuckPerms on the proxy rather than in the config file.

Sizing the proxy on a panel host#

Neither proxy is heavy. Half a gigabyte of heap is plenty for either at a few hundred players; the work is CPU spent compressing and encrypting traffic. A proxy on a 1-2 GB plan with one core is normal. The backends are where the money goes.

bash
$ java -Xms512M -Xmx512M -XX:+UseG1GC -jar velocity.jar

A network on any panel host is one server per process: a proxy plus a lobby plus two gamemodes is four servers, each with its own memory limit, port and backups. On RE:NODE each Minecraft plan comes with one port allocation and you can add more on the Network tab; SFTP credentials are per server, which is how you push the same forwarding.secret to every backend without retyping it. Every server is its own container with its own public port, so the direct-connection test in the forwarding section is not a formality - modern forwarding is what keeps those backend ports closed to impostors. The general case for splitting work like this is in CPU vs RAM for game servers.

Once the proxy is up, put a name in front of it with an A record and an SRV record, so players type mc.example.com and nothing else - SRV records for Minecraft has the exact record.

Troubleshooting the switch#

Velocity logs "Your server did not send a forwarding request to the proxy". The backend is not set up for modern forwarding: proxies.velocity.enabled is still false, the file edited was the wrong one for that Paper version, or the backend was not restarted.

Players are kicked with "Unable to verify player details" or a decoder error. The secret on the backend does not match forwarding.secret. Look for a trailing newline or space from the copy.

"If you wish to use IP forwarding, please enable it in your BungeeCord config as well!" This is the backend saying it still has bungeecord: true in spigot.yml while the proxy is not sending BungeeCord-style data. Set it to false on Velocity with modern forwarding.

Everyone logs in as a new player. Forwarding is off or in none mode, so backends see offline-mode UUIDs. Do not let anyone play until it is fixed; each login creates player data you will have to clean up.

A plugin that worked on BungeeCord does nothing. It was a BungeeCord plugin sitting in Velocity's plugins folder. Velocity logs that it could not load it at startup; scroll up.

Staff lost their admin commands. BungeeCord's config.yml groups were doing the permissions. Grant the Velocity nodes in LuckPerms. The LuckPerms guide shows how to scope them to the proxy with a server context.

FAQ#

Is BungeeCord still maintained?

Yes. md_5 updates it for new Minecraft versions, and it remains widely used. It is not abandoned; it is simply less secure by default and slower than Velocity, and its forwarding needs a firewall or BungeeGuard to be safe.

Can I run BungeeCord plugins on Velocity?

No. The two have separate plugin APIs. Look for a Velocity build of each plugin; most popular network plugins have one. Backend plugins that only use the BungeeCord messaging channel do keep working.

Do I need to change anything on the backends when migrating?

Yes, one switch each: turn off bungeecord in spigot.yml, enable Velocity support in Paper's global config, and paste the forwarding secret. Worlds, plugins and player data stay as they are.

My backends run 1.12.2. Can I still use Velocity?

Yes, with legacy or bungeeguard forwarding instead of modern. You lose the built-in protection, so add BungeeGuard or keep backends unreachable from the internet - the same precautions BungeeCord needs.

Will players notice the migration?

Only the downtime and, if you changed it, the MOTD. The address stays the same, UUIDs stay the same if forwarding was correct before and after, and server names can stay the same so existing selector menus keep working.

Is Waterfall safe to keep running?

It runs, but it no longer gets protocol updates or security fixes. Move to Velocity, or back to BungeeCord, before the next Minecraft version you want to support.


Comments

Completely anonymous: no account, no email, no cookie. We store the name you type, the text and the time - nothing else. Links are limited and markup is not rendered.

0/2000