YiorasHost / Redline

Find out what is actually limiting your Minecraft server.

Redline is a free Paper plugin. It stress-tests a server with no players on it and tells you which single thing is holding it back — the CPU it is allowed, the size of its heap, or one specific kind of work your world is doing — with the measurement that led to that conclusion printed underneath it.

Download redline-1.3.0.jar Read the method first

Paper 1.21.x only. Not Spigot, not Folia — it refuses to run rather than guess. v1.3.0 · beta

What you actually get

One verdict, in the console, with the numbers that produced it. This is a real run against a test server we deliberately gave a 512 MB heap, so it is the RAM answer:

VERDICT: RAM-LIMITED
  Holding 1369 chunks of world resident — roughly 9.3 players' worth at this server's view
  distance of 10 — left over 75% of the 512MB heap live after a full collection, against a
  70% threshold.
  Collection cost 2.20ms of every tick under load (332 collections over 69s).
  CPU was not the constraint here: the container hit its quota in only 1.6% of scheduling
  periods.

Note the last line. Redline says what is not the problem as well as what is, because telling an owner to buy memory to fix a CPU limit is the most expensive wrong answer this tool could give. The other verdicts read CPU-LIMITED or WORKLOAD-LIMITED naming the specific workload, and each one clears the other two resources explicitly.

There is no score

Redline never prints a 0–100 number. Its redstone workload is deliberately brutal, so a perfectly healthy server does badly on it — and a number that turns “our test is hard” into “your server is failing” is worse than no number at all. You get a named limit and the measurement behind it.

Running it

1. Drop redline-1.3.0.jar into plugins/ and restart.
2. Make sure nobody is online — it will refuse otherwise.
3. /redline run
4. Read the console. A JSON report is written to
   plugins/Redline/reports/ at the same time.

The whole run takes three to six minutes. Other commands: /redline status, /redline cancel, /redline env.

It will not run on

“Why not just use spark?”

Use both. Redline calls spark; it is not a replacement for it.

spark profiles what your server is doing right now. When something is already wrong, spark is the tool that finds it, and nothing here comes close to its profiler.

Redline answers a different question: what can this server take, and what runs out first? It applies known load in controlled steps to a server with nobody on it, so the answer is about capacity rather than about this afternoon. That is a question spark does not ask, because it is not a load generator.

Concretely, the difference is what you do with the answer:

QuestionTool
“The server is lagging right now — what is doing it?”spark
“Which of my forty plugins costs the most tick time?”spark’s profiler is better than Redline’s scan. Redline’s is a 20-second sample and says so.
“Will this server hold twenty players, or do I need a bigger one?”Redline
“Is it my CPU limit or my RAM that I keep hitting?”Redline
“Did the change I just made actually help?”Redline, run before and after

Redline reads spark for its garbage-collection and CPU statistics through spark’s public MIT-licensed API, on the spark that Paper already bundles from 1.21 onward. If spark is not answering, Redline refuses to run rather than fall back to something less trustworthy.

To be precise about what that means: spark’s public API has six methods and none of them expose its profiler. Redline’s per-plugin figures come from its own 100 Hz sampling of the server thread, not from spark. If you want real per-plugin profiling, run /spark profiler — it is better, and it is already installed.

How it measures

Redline creates its own world, far from yours, and puts everything back afterwards. Five stages, in this order:

  1. Idle baseline. Ten seconds of tick times with nothing happening, so everything after it is a difference rather than an absolute.
  2. Plugin scan. Twenty seconds sampling the server thread at 100 Hz, attributing each sample to the deepest plugin frame on the stack. Resolves down to roughly 0.13 ms/tick; anything smaller is reported as “below this scan’s resolution”, never as zero.
  3. Five workloads, one at a time. Chunk generation, mob AI and pathfinding, hopper item movement, redstone update cascades, explosion physics. Each runs alone for ten seconds so its cost is attributable, and each is ranked by p95, not average — players feel stutter, not means. The report shows the median next to the p95 for every one of them, because those two numbers answer different questions: the median is what play feels like most of the time, the p95 is what stutter feels like, and a server being throttled shows up in the first long before it changes the second.
  4. World residency. A 1,369-chunk area is held loaded and ticking, then two full collections are forced and the live heap is measured. This is what actually fills a Minecraft server’s memory, and it is how the RAM answer is produced.
  5. World capacity. The share of the heap that reference area occupies is scaled up to the whole heap, giving the number of chunks this server can hold resident. Scaled from one measured share rather than fitted to a line, and it charges the server’s own baseline against the world, so it errs low.
  6. CPU, one thread and all threads. Identical synthetic arithmetic run first on a single thread and then on every thread the container can see, off the server thread. The first number governs tick speed; the second is what extra cores actually buy. The ratio also shows whether the cores you were promised are there.
  7. Durable-write latency. A region-file-sized block written and fsynced forty-eight times, off the server thread. This is the write a Minecraft server waits on when it saves a chunk, and it is the measurement that separates a local disk from network storage. fsync and not chunk-load time on purpose: a read is served out of the page cache and gets faster every time you run it on the same world, whereas a durable write cannot be flattered by a cache.
  8. Idle CPU contention. While the server sits idle, the kernel’s own pressure-stall counter for this container is read and the share its CPU quota accounts for is subtracted. What is left is time this server’s threads spent waiting for a CPU for some reason other than its own limit.
  9. Parallel terrain generation. Chunks generated asynchronously with the worker pool saturated. Measured but not reported — see below.

Why the contention figure is read at idle and nowhere else

Because under load it means nothing. A Minecraft server running flat out has far more runnable threads than any plan has cores, and they queue behind each other — that queueing is indistinguishable, in the counter, from a neighbour competing for the machine. Measured on a deliberately idle host, a container given a generous quota and eight of its own busy threads reported 20.8 ms per second of “unexplained” waiting with nothing else on the box at all.

At idle, with one thread runnable, that explanation is not available. The same container on a quiet host read 0.08 ms/s; with twenty-four competing threads on the machine it read 15.5 ms/s, neither of them throttled. That is the measurement, and it is reported as an observation about the minutes the run happened to occupy — not as a verdict, and never as a claim about anyone’s host. Contention moves with the time of day. One run is one moment.

One measurement is taken and deliberately not shown

The parallel generation rate is in the JSON and nowhere else. Across three runs from three fresh starts of the same server it read 23.7, then 28.0, then 33.0 chunks per second, climbing every time: the test skips chunks that already exist, so each run walks its spiral further out into different terrain with more of the region files already cached. A figure that cannot repeat itself on one server cannot be used to compare two. It is kept in the raw data for anyone auditing the run, and left off the page.

Why there is no player count

Because it cannot be measured honestly, so v1.2.0 removed it. Real clients cannot be faked: an online-mode server rejects unauthenticated logins and no bot library speaks the current protocol. What earlier versions called a simulated player was a chunk ticket plus twenty mobs, which leaves out packet encoding, per-connection entity tracking, view synchronisation and chunk sending — most of what a real player actually costs.

The result read 0.18 ms per player and drew a flat line still under 13% of the tick budget at eighteen players, on a container correctly sold for one to four. That is not a tuning error that a caveat can fix, and a caveat under a chart does not outweigh the chart. It went the same way as the 0–100 score: deleted rather than shipped with an asterisk.

What it cannot measure

Every item below is a real limit. Read it before you trust a number.

What uploading adds

Nothing is sent unless you run the upload command, and the console prints exactly what would go before it goes. What you get back, besides a page you can link to, is the one thing a benchmark cannot tell you on its own: whether a number is good. Where enough runs have been uploaded, the report page puts your single-thread speed, your world capacity and your durable-write latency beside the others.

Two things keep that honest. Below five uploaded runs nothing is shown at all, because a rank out of four is not a fact; below thirty it is given as a count rather than a percentile. And every such line says the same thing about itself: the servers in that comparison belong to people who went looking for a problem, so it is not a picture of hosting in general. A run only enters the comparison if it is comparable — a settled JVM, no abort, and the first run since that server started, all of which the report records about itself.

Our own numbers, unedited

If a hosting company publishes a benchmark that only ever runs on other people’s servers, that is the first thing anyone should check. So here is ours, produced by the same jar you can download above, with nothing removed.

Measured 2026-08-12 on node02 — the same physical machine that runs customer servers — inside a container with the same cgroup limits as an Iron plan: 3.00 CPU cores, 6 GiB container, 5 GiB heap, Paper 1.21.11 on Java 21, view distance 10, one plugin. Three consecutive runs on a settled JVM and a freshly generated benchmark world. Every figure carries its 95% interval.

whatrun 1run 2run 3
verdictWORKLOAD-LIMITED: redstone — in all three
idle tick cost (p95)0.4 ±0.1 ms0.1 ±0.1 ms0.4 ±0.1 ms
redstone — p95 added47.1 ±7.0 ms43.8 ±4.1 ms44.8 ±8.3 ms
mob AI — p95 added7.3 ±3.8 ms6.3 ±4.7 ms6.3 ±3.8 ms
explosions — p95 added5.1 ±1.9 ms5.5 ±2.1 ms5.5 ±0.6 ms
hoppers — p95 added0.9 ±0.6 ms1.2 ±0.6 ms1.0 ±0.4 ms

One row does not agree across all three runs and is published that way rather than tidied. Idle tick cost moves by three tenths of a millisecond, which is enough to break the overlap at an interval of ±0.1 ms and means nothing for any verdict. The workload rows, which are what the verdict rests on, all overlap.

These figures replace a set measured on 2026-08-07. The hopper and explosion workloads were rebuilt on 2026-08-12 after both were found not to be measuring what they claimed: the hoppers were never actually loaded with items, and the explosions were configured not to break blocks, which skips almost everything an explosion costs. The full write-up is in the tool's EVIDENCE.md.

On this container the synthetic redstone workload is what runs out first, and it is deliberately brutal — that is not a statement that the container is bad. Nothing was CPU-throttled and nothing was short of memory. Its CPU is a shared limit, not a reserved core.

Every interval above overlaps across all three runs. That is what we mean by reproducible: not that the digits repeat, but that the measurements agree once each carries its own uncertainty. The interval is the wider of the confidence interval on the percentile itself and half the gap to an independent warm-up window of the same workload in the same run.

Redline reports no world-generation rate and no heap residency in megabytes. Both were measured and neither survived that test — identical runs disagreed by a fifth, and for residency the spread was invisible from inside any single run. A figure that will not reproduce is not evidence, so neither is in the tool. Residency is still measured; it is reported as the thing it decides — whether the heap held the world — which is identical in every run.

Method and caveats for these figures are recorded in our public claims register. The most important one: node02 had no customer servers on it when this was measured, so these numbers show the hardware without contention. A shared node with neighbours on it will measure differently, and that is the honest reason this is a reference point rather than a promise.

What changed in v1.2.0

The simulated-player ramp was removed, along with the per-player cost and the player-count chart. If you ran v1.1.0 and are looking for that number, it is gone deliberately. It could not be measured honestly — the reasoning is under How it measures — and it read 0.18 ms per player with no ceiling at eighteen on a container correctly sold for one to four. Nobody should size a server on that.

Three measurements replaced it, all of which actually separate a small server from a large one, which the old report largely failed to do:

A parallel terrain-generation rate is also measured. It is not shown anywhere, because it does not reproduce — see How it measures.

The report page was rebuilt around three plain answers — what is limiting this server, is it out of CPU or RAM, and how does normal play feel — with every workload row now leading with its median rather than its p95. Showing only the p95 made a throttled server and an idle one look alike, because a Minecraft tick is one thread and one thread spikes about the same on both.

Two fixes worth naming, because they mean older numbers were wrong: the hopper workload was never actually holding items (a Bukkit snapshot write that does not persist, so it measured 2,401 empty hoppers), and the explosion workload was not breaking blocks, which skips almost everything an explosion costs. Both were rebuilt on 2026-08-12. Runs are also about twice as fast now that the ramp is gone.

Uploads and privacy

The plugin transmits nothing. Not on start, not on a timer, no version check, no analytics. The only network call in the jar is the one behind /redline upload confirm.

/redline upload on its own sends nothing — it prints the exact bytes that would be sent and stops. Sharing takes a second, explicit command.

A report contains no IP address, hostname, server name, world name, player name or file path. Those are not filtered out at upload time; they are never collected, so there is no version of the report file anywhere that has them. JVM flags are filtered at the point of collection to memory and collector settings only, because the raw argument list routinely carries directory paths and occasionally credentials.

Shared reports live at redline.yiorashost.com and every individual report page is noindex. There is currently no way to delete an uploaded report once you have sent it.


Redline is closed source and free. It is made by YiorasHost, a small Minecraft host in Helsinki, because we needed the measurement for our own hardware and there was nothing that answered the question honestly. If it tells you your server is fine, that is the whole answer and there is nothing else here for you.