Meridian

Progress, tests and benchmarks

Where the project is

2.5×less processor for the proxy with the optimisation (pull request #160) MeasuredMeasured before and after on the same bench: 2.6 times at 500 typical players, 2.3 times at 1,000.
1,000typical bot players held by one proxy on one PC MeasuredWith bots and synthetic game servers; with real Horizon servers, the tests are in progress.
0players lost in that test MeasuredOne hour at 1,000 typical players.

Meridian is a working proxy: it routes players, balances load and moves them between servers without a loading screen, and it held 1,000 typical bot players on one PC with 0 players lost. An optimisation that cuts the processor use by about 2.5 times has been merged (pull request #160).

Meridian is a proxy for Horizon, a Rust version of Minecraft Java Edition. Players connect to the proxy, and it sends each of them to one of several servers behind it, and can move a player to another server without a loading screen.

With the Horizon team

Meridian is developed in the open, as a project separate from Horizon. The Horizon team, the maintainers of Horizon, gave directions on how to go about it, and they decide what goes into Horizon itself. Their requests are on a public issue of Horizon: small pull requests, one at a time. These directions are not an endorsement of Meridian.

See Horizon issue #7484.

What was asked and what is done: Roadmap.

Before and after the optimisation

Before (main) (commit 57930e6) · After (writes of one read grouped) (commit c38a01e (merged, #160))

With game servers that send a tick's packets together, as real servers do, the proxy now spends about 2.5 times less processor per packet: 1,000 typical players need about 2.6 cores instead of 6.2.

Processor for 1,000 players

of the 8 cores the proxy may use

Before6.17 cores
After2.62 cores

2.4 times fewer cores

Measured

Cost of one packet

500 typical players

Before20.31 us
After7.92 us

2.6 times less processor

Measured

Slowest 1 % of round trips

500 typical players

Before15.09 ms
After2.67 ms

5.7 times lower

Measured

Packets sent in one go

to each player

Before1 packet
After12.5 to 17.1 packets

12 to 17 packets in each write instead of 1

Measured

Memory per player

the price of the change

Before524 KB
After532 KB

+1.3 % (5 % allowed)

Measured

Nothing is lost for it: the same packets reach the players, no player was dropped, and the memory per player stays within about 1 % of before.

Where there is nothing to group, nothing changes. This was measured on one PC with bots and checked with a real server; it is merged (pull request #160).

Every measure, one by one

Processor per packet, 500 typical players

2.6 times less processor
Before
20.31 us Measured
After
7.92 us Measured

servers that write once a tick (every 50 ms), as real ones do

Processor per packet, 1,000 typical players

2.3 times less processor
Before
19.03 us Measured
After
8.11 us Measured

Proxy cores, 1,000 typical players

2.4 times fewer cores
Before
6.17 cores Measured, to watch
After
2.62 cores Measured

the 8 threads the proxy was given: 8 cores (the tick on the bars).

Packets per write to the players

12 to 17 packets in each write instead of 1
Before
1 packet Measured
After
12.5 to 17.1 packets Measured

with a real game server: 14.6 to 16.6

Memory per player, 1,000 typical players

+1.3 % (5 % allowed)
Before
524 KB Measured
After
532 KB Measured

at 500 players: 514 before, 499 after. The first version cost +19 %; it was fixed.

Latency p99 through the proxy, 500 typical players

5.7 times lower
Before
15.09 ms Measured
After
2.67 ms Measured

p99: 99 round trips in 100 are faster than this. The 50 ms server tick is part of these figures.

Latency, 1,000 typical players

not judgeable
Before
no number Not judgeable
After
no number Not judgeable

the bots run on the same PC and were the limit

Control: servers that send each packet alone control

no change
Before
24.58 us Measured
After
24.72 us Measured

nothing to group here, so nothing should change: it shows that the gain comes from the grouping alone

A control row is a case where nothing should change. It shows that the gain comes from the change alone.

How many players?

We test with bots that act like players, on one PC. Each number says how sure we are of it:

Light players

little traffic: 20 small packets and 2 chunks a second each (the first benchmark's profile)

Shown to work
1,500 players Measured
2.39 cores of processor
2.39 cores of the proxy, before the optimisation (it changes little for light traffic)
Not shown
2,000 players Not judgeable
the test machine was the limit: the proxy itself had room (3.5 cores)

Typical players

stand and walk about half of the time; built from one real client (275 small packets and 3.5 chunks a second each)

Shown to work
1,000 players Measured
2.62 cores of processor
2.62 cores with the optimisation (commit c38a01e, merged as pull request #160); 6.2 cores before. Its latency could not be judged: the bots were the limit.

Heavy players

walking more than half of the time (the stress profile)

Shown to work
500 players Measured
6.4 cores of processor
6.40 cores before the optimisation, servers writing each packet alone; 1,000 heavy players were not run

What 1,000 typical players cost

Processor
2.62 cores Measured
33 % of 8 cores (the 8 threads the proxy was given on the test PC).
6.2 cores before the optimisation; in online mode (encryption) about 1.4 more cores is an estimate
Memory
0.53 GB Measured
7 % of 8 GB (the VPS).
Bandwidth, each way
660 Mbit/s Measured, over the limit
132 % of 500 Mbit/s (the Internet line).
about 83 MB/s to the players, and as much from the servers to the proxy; counted before compression, so on the wire it is less

What that means for smaller machines

The machines

The test PC

  • Windows 11
  • Intel i9-14900KF: 8 fast cores (2 threads each) + 16 efficiency cores
  • 64 GB of memory
  • The proxy was given 8 threads (4 fast cores); the bots used the other cores

The VPS

  • A KVM virtual machine, Linux (Ubuntu 26.04 LTS, kernel 7.0)
  • 4 virtual cores (1 thread each), shown as Intel Core Processor (Haswell) at 3.0 GHz; the exact model is hidden by the host
  • 8 GB of memory (7.6 GiB usable), no swap
  • 75 GB disk, NVMe according to the provider's offer (the virtual disk does not say)
  • Network: up to about 3 Gbit/s according to the provider's offer; not measured
  • Cores are shared: no sign of contention at rest (0.0 % stolen time), not tested under load

The Internet line

  • 500 Mbit/s down and up (advertised)

Real-network tests

Real game servers, real game clients, a real network between them. Few players, but no bots and no shortcut.

real network run (VPS + PC), 8 November

Real players in the test
3 players Measured
Moves from one server to another and back
56 of 56 ok Measured
Time in seconds: 1.4 to 2.1
A server that stops with players on it
3 of 3 moved out when server B stopped Measured
How fast the players were moved out
1.5 s per player, one every 2 s Measured
A server that stops at once
3 of 3 players fell back to the other server, no title screen Measured
Time in seconds: 0.011 to 0.123 (proxy side)
One player was still being moved when the server kicked him: the fix from this week caught it (123 ms).
A server that crashes
3 of 3 players fell back after the server process was killed Measured
Time in seconds: 0.021 to 0.025 (proxy side), 0.9 to 1.7 seen on screen
Quick reconnections
5 of 5 quick reconnections joined, no error Measured
The client came back under another name, so this checks the reconnection, not a returning player's data.
Packets grouped in each write
14.6 to 16.6 packets Measured
Memory of the proxy
11 MB with 3 players at rest; 67 to 105 MB at rest after 20 to 60 transfers Measured, to watch
A plateau, not a steady climb (it fell back to 91 MB after more transfers). Not yet compared with the old proxy.

Real server on the VPS, one on the PC, 3 real clients, final proxy. Not tested here: the game server's own speed (TPS), many players.

Roadmap

What is done and validated, what is in progress, and what is planned.

A task is marked done only when it is finished and validated (merged and checked), with a public proof and its date.

With the Horizon team · The roadmap of Meridian

With the Horizon team

Requested by the Horizon team and validated

A request is validated when its pull request is merged into Horizon.

Done
A server tells the proxy its state (transfer-status)

A Horizon server tells a proxy how many players it holds and whether it takes more, before players are sent to it.

Proof: Horizon pull request #10527 · validated 2026-11-06

Done
No move onto a full or stopping server

A Horizon server turns down a player sent to it when it is full or stopping, and the player stays where they were.

Proof: Horizon pull request #11428 · validated 2026-11-07

Done
A stopping server waits for the proxy

Before it stops, a Horizon server gives a proxy a few seconds to move its players to another server.

Proof: Horizon pull request #11713 · validated 2026-11-08

Done
Riders turn as in the original game

A fix in Horizon for players riding an animal or a vehicle, merged by the Horizon team.

Proof: Horizon pull request #12260 · validated 2026-11-08

Done on our side, waiting for the team's answer

What the Horizon team asked for on the issue, done and checked by us; their answer is still to come.

Done
The hand-over test on Horizon's main branch

The end-to-end test of moving a player between two Horizon servers, run on Horizon's main branch as asked: 31 of 31 checks, in 3 runs out of 3.

Proof: the results, posted on the issue · validated 2026-11-06

Done
One public issue for the news of the proxy

The news of Meridian go to one issue of its own repository, as asked, and no longer to Horizon's.

Proof: issue #117 · validated 2026-11-06

Waiting for the Horizon team's review

Our one open pull request in Horizon: one at a time, as asked.

In progress
The recipe book on a Paper server

Horizon's recipe book takes the entries that the server sends, so it works on a Paper server. Ready for review since 8 November; its automatic checks pass.

Proof: Horizon pull request #12496

Side work we do in advance while we wait

Work on Meridian's side that needs nothing from Horizon. Each one is on the roadmap below.

In progress
A crash report on Horizon, looked into

A crash of Horizon when leaving a server or a world: we read the log that came with it, and we wait for the answer of the person who reported it.

Proof: Horizon issue #11678

The roadmap of Meridian

5 of 13 validated

Done Done (validated)

Done
Fewer writes to each player

The proxy now sends a server's packets to a player in one write instead of one write each: about 2.5 times less processor, measured before and after, then tested on a real network.

Proofs: pull request #160, the measures, before and after · validated 2026-11-08

Done
Three fixes: the health check, evacuations, the documents

The metrics page and the health check answer at once, the summary of an evacuation counts every player, and the documents say what Horizon's stop wait changes.

Proofs: pull request #151, pull request #152, pull request #154 · validated 2026-11-08

Done
A test on a real network with real servers and clients

Real Horizon servers, three real game clients and a real network: moves between servers with the inventory kept, a server that stops with players on it, and a server that crashes, its players falling back to the other one.

Proofs: the test on a real network, 8 November, pull request #161 · validated 2026-11-08

Done
This public progress page

A public page that shows what was measured and what was not, in English and in French.

Proof: the progress page · validated 2026-11-08

In progress In progress

In progress
Load tests with real Horizon servers

Bots that act like players, on real Horizon servers behind the proxy: 50 players first, then 250, 500, and 1,000 on one PC.

In progress
Orders from extensions

An extension will be able to ask the proxy for things: read the players, send a message, move or kick a player, drain or reload a server, and, last, run a line of the proxy's console. Eight pull requests, one at a time.

1 of 8 steps validated

  1. Done The order dispatcher, with a limit of orders per second Proof: pull request #163 · validated 2026-11-08
  2. In progress The client side in the extension kit (SDK)
  3. Planned Read the players and the servers
  4. Planned Send a message
  5. Planned Move players
  6. Planned Kick a player
  7. Planned Drain or reload a server
  8. Planned The proxy's console, last

Planned Planned

Planned
Events for extensions

The proxy will tell extensions what happens, such as a player who joins or leaves, in three pull requests.

Planned
Extension commands tested end to end

A real game client types an extension's command through the proxy; the test checks that the server never saw it, also while the extension is stopped and when it comes back.

Planned
Reuse the compressor (a second optimisation)

Keep one compressor for each connection instead of setting up a new one for every large packet, to cut the processor use again.

Planned
The state of the servers, given to extensions

The proxy will pass the state of each server to extensions, so that they can choose better where a player goes.

Planned
A network simulator, and automatic scaling

Test the proxy over a poor network (delay, loss) with a simulator, and start or stop servers by themselves as players come and go.

Planned
Several proxies working together

Only if the goal goes past 2,500 players: several proxies that share the players and the servers.

Not tested yet

This list is part of the results. If something is not shown on this page, it has not been measured.

Measured on one PC, with synthetic bots and real servers (see each row). The optimisation is merged (pull request #160).