If you have ever typed “is the server lagging?” into Discord and received six different answers, you already know why this article exists. Somebody points at the memory graph. Somebody else says the TPS counter is fine. A third person blames a plugin nobody has updated since 2021. None of those answers is grounded in the one number that actually describes how a Minecraft server is doing its job: the time it takes the main thread to finish a single tick.
This guide is written for server owners, administrators, and staff who want to stop guessing. It explains what the tick loop is, why 50 milliseconds is the number that matters, and how to read MSPT and TPS together so the data tells you where the problem actually lives. There is no hand-waving here and no “just add more RAM” advice, because that advice is wrong often enough that it deserves its own section below.
The numbers in this article come from a controlled test, not from a wiki table. The host was an Intel Core i5-13400F with 16 threads and 14 GB of RAM, running Ubuntu 26.04 on OpenJDK 25.0.4.1 with Paper 26.2 build 129 and the flags -Xms2G -Xmx4G -XX:+UseG1GC. The world was pre-generated to 22,801 chunks with Chunky, no players were online, and a 240×240 area was force-loaded so entities would actually tick. Every figure below was collected with Paper’s own tick query across a rolling 100-tick sample, ten samples per load, reporting the median. If you want to reproduce it, the measurement section tells you exactly how.
How the Minecraft Tick Loop Actually Works
Minecraft is not event-driven in the way most software is. It runs a fixed-timestep loop: the server wakes up, processes everything that is scheduled for “this tick”, then sleeps until the next one. Twenty times per second, without exception in the target design. That is the whole model. Every mob that moves, every block that updates, every redstone torch that flips, every hopper that transfers an item, and every player packet that gets processed happens inside that loop. If the loop is slow, everything is slow, because nothing else runs until the loop comes back around.
The official documentation is blunt about this being intentional. The Minecraft Wiki tick page describes the fixed 0.05 second step, and the ticks per second page covers how the game reports and clamps that rate. Paper inherits the model and adds tooling on top, which is why the Paper documentation is the practical reference for anyone running a modern server.
The 50 millisecond budget
One second divided by twenty ticks is 50 milliseconds. That is the entire budget for a single tick. Everything the main thread has to do in that tick must fit inside 50 ms, or the tick runs long and the server falls behind schedule. What happens next is the part people misunderstand. The server does not “catch up” by doing less work. It simply starts the next tick late, and the game clock drifts. Players see it as rubber-banding mobs, hit registration that misses, blocks that break and then reappear, and eating that takes three seconds instead of one.
A tick that overruns has three practical consequences:
- The next tick starts late, so the effective tick rate drops below 20.
- Scheduled work piles up, because the queue does not shrink when the loop is slow.
- Network position updates go out late or get skipped, which is why movement feels choppy before the TPS number looks bad.
Why TPS falls in whole-tick steps
TPS is not a continuous dial. The server counts ticks completed in a rolling window, so a tick either finishes in the window or it does not. Over a one-second sample you can only report whole ticks, which is why practically every server you will ever see reports 20.0, 19.x, 18.x, or a lower number that lands on a fraction of twenty. A server does not report 17.53 TPS because it is a little slow. It reports that number because the rolling window straddled a boundary, and the underlying reality is that some ticks took far longer than 50 ms.
This is the single most important thing to internalize before you read any performance graph: TPS is a coarse output, and MSPT is the input. TPS tells you the consequence. MSPT tells you the cause. If you only ever look at TPS, you are reading the smoke alarm instead of the thermometer.
The Tick Budget Formula and Conversion Table
The arithmetic you need is short enough to memorize, and once you have it, you can convert any MSPT reading into the percentage of the budget it consumes without opening a spreadsheet.
tick budget used (percent) = (MSPT / 50) x 100
ticks per second, while MSPT is at or under 50 = 20
ticks per second, once MSPT exceeds 50 = 1000 / MSPT
for example: MSPT 121.2 -> 1000 / 121.2 = 8.25 TPS
The second formula is an approximation, and it is a good one for diagnosing a struggling server, but be aware of what it assumes: that every tick is roughly the same length. Real servers have a mix of cheap ticks and expensive ones, so a server with a 45 ms median will still dip below 20 TPS whenever a spike lands. Treat the formula as a sanity check, not a guarantee.
| MSPT | Budget used | Approximate TPS | What it means |
|---|---|---|---|
| 10 ms | 20% | 20 | Comfortable. Plenty of headroom for spikes. |
| 25 ms | 50% | 20 | Healthy steady state. This is the target zone. |
| 40 ms | 80% | 20 | Working, but a spike will push you over. |
| 50 ms | 100% | 20 | The edge. Any variance at all now costs you TPS. |
| 60 ms | 120% | 16.7 | Ticks are consistently late. Players notice. |
| 100 ms | 200% | 10 | Half speed. Mobs, redstone, and farms all slow down. |
| 121 ms | 242% | 8.3 | Our 20,000 mob test load. Clearly overloaded. |
Notice how 40 ms and 50 ms both still report 20 TPS. That is not a reason to relax. At 40 ms, four out of every five milliseconds of your tick are already committed, and the only thing keeping you at 20 TPS is that nothing unusual has happened yet. On a live server, something unusual happens constantly.
How to Measure MSPT Without Fooling Yourself
Measurement is where most performance investigations go wrong, and it is almost always the same mistake: one reading, taken once, treated as fact. Below is the order that actually produces usable data.
Start with the built-in tick query
Paper ships a tick command that reports a rolling sample of recent ticks rather than an instantaneous value. Run /tick query on a Paper server and you get a median alongside the smoothed TPS figure. Run it repeatedly, at least ten times, spread over a minute or two, then take the median of those medians. A single query is one hundred ticks of context, which is five seconds of live server behavior. Five seconds is not a diagnosis.
- Use
/tick queryfor the median and the reported TPS. - Use
/tick sprinton a test server to fast-forward ticks and check whether the cost is stable or time-dependent. - Run your samples with a realistic player count, in the same dimension and near the same coordinates players actually use.
- Record the numbers in a file. Memory of “it felt about forty” is worthless a week later.
Read the percentiles, not just the median
A median tells you what a typical tick costs. It tells you nothing about the tick that cost 1,027 ms. Percentiles do. When you sample with spark, look at P95 and P99 alongside the mean. P95 above 40 ms means one tick in twenty is already eating four fifths of the budget. P99 above 50 ms means roughly one tick per hundred is over budget, and those are exactly the ticks players feel as a stutter.
Our own test made this vivid. The median held near 50 ms during a large entity spawn, but the 99th percentile spiked to 1,027 ms. Same run, same server, same load. A dashboard showing only the average would have called that moment healthy while players were staring at a frozen world.
Treat log lines as a hint, not a source of truth
Older and non-Paper server software prints a “Can’t keep up! Did the system time change, or is the server overloaded?” warning. It is genuinely useful as a signal that something crossed a threshold, but it cannot carry an investigation. The message fires on a specific internal condition, it is suppressed by rate limiting, and it says nothing about magnitude or cause. If that line is the only evidence you have, you do not have evidence yet. You have a prompt to go run /tick query and spark.
MSPT Is Not CPU Load, and It Is Definitely Not RAM
These three numbers get collapsed into “server performance” in casual conversation, and that collapse is expensive. MSPT measures one specific thing: wall-clock time spent by the main server thread inside a tick. It is not total CPU utilization, because your host has other threads doing chunk generation, networking, and garbage collection, and those can be pinned at 100% while the tick loop stays under 25 ms.
RAM is even further removed. Adding memory does not make a mob AI pathfinding calculation faster. It can help in one narrow case: if your heap is too small, the garbage collector runs more aggressively and its pause times show up as MSPT spikes. That is a real effect and it is the reason running a busy server on 1 GB of heap is a problem. But once you have enough heap to avoid constant collection, extra gigabytes do nothing for a CPU-bound tick loop.
- High MSPT with low CPU: the main thread is waiting, possibly on synchronous I/O or lock contention.
- High MSPT with high CPU: genuine compute load, usually entities, AI, or plugin logic.
- Low MSPT with high RAM use: normal. Minecraft allocates freely and collects later.
- Spiky MSPT with visible GC pauses in spark: heap sizing or allocation rate, not entity count.
The practical takeaway: when someone tells you the server needs more RAM, ask for an MSPT graph first. You will save money.
What a Controlled Test Actually Showed
The test that produced the figures in this article was built to isolate one variable at a time. Same world, same JVM, same flags, no players, no plugins beyond what Paper ships. The 240×240 force-loaded area guaranteed that the entities were genuinely inside ticking chunks rather than sitting in unloaded space, which is a mistake that silently invalidates a lot of home-grown benchmarks.
| Load | Median MSPT | TPS | Budget used |
|---|---|---|---|
| Idle, only the force-loaded area | 0.6 ms | 20.0 | 1.2% |
| 1,000 zombies, NoAI | 8.3 ms | 20.0 | 16.6% |
| 5,000 zombies, NoAI | 22.7 ms | 20.0 | 45.4% |
| 10,000 zombies, NoAI | 48.5 ms | 20.0 | 97.0% |
| 20,000 zombies, NoAI | 121.2 ms | 8.25 | 242.4% |
| 2,000 zombies, AI enabled | 19.1 ms | 20.0 | 38.2% |
| 5,000 zombies, AI enabled | 28.5 ms | 20.0 | 57.0% |
| 10,000 armor stands | 19.2 ms | 20.0 | 38.4% |
| 5,000 dropped items | 20.7 ms | 20.0 | 41.4% |
| 2,000 villagers | 113.8 ms | 8.79 | 227.6% |
Also worth noting: /save-all flush took 0.16 to 0.36 seconds on this world. That is 160 to 360 ms of main-thread work landing in a single tick, which is why save operations are a recurring source of complaints on large worlds and why Paper offers configuration options for spreading that work out.
Scaling is linear, until it is not
From 1,000 to 10,000 NoAI zombies, the cost grows almost perfectly linearly: about 8.3 ms per thousand entities. That predictability is useful, because it means you can estimate your own load. Ten thousand simple entities roughly costs you half your tick budget. What breaks the pattern is allocation pressure. At 20,000 entities the curve steepens sharply, because the server is now generating enough garbage per tick that collection cycles start landing on the main thread. Linear scaling is the design; the cliff is the surprise.
This is also why a server can look fine at 6,000 entities and fall apart at 8,000. Nothing magical happened to the mobs. The allocation rate crossed a threshold where the collector has to work harder, and that work shows up in the tick.
AI is the difference between cheap and expensive
Setting the NoAI flag on a mob stops it running its AI goals, and the performance consequence is enormous. Two thousand AI-driven zombies cost 19.1 ms. Two thousand NoAI zombies would have cost roughly 5 ms by extrapolation from the linear curve. Villagers are worse still: 2,000 of them produced 113.8 ms, worse than twenty thousand NoAI zombies. Villager AI involves pathfinding toward workstations, inventory scanning, breeding checks, and gossip management, all of which runs every tick for every villager in a ticking chunk.
If you run iron farms or trading halls, this is the number to remember. Two hundred villagers in one trading hall is not a trivial load. Two thousand is a design emergency.
Cheap per entity still adds up
Armor stands do almost nothing: no movement, no AI, no collision resolution beyond a bounding box. Ten thousand of them still cost 19.2 ms, which is just under 40% of the budget. Dropped items are similarly cheap individually, and 5,000 of them cost 20.7 ms. The lesson is that “this entity is cheap” and “this entity is cheap at scale” are different claims. An armor stand shop with display models is fine. A duplicator stalling five thousand item stacks in one chunk is not.
Averages hide the moments players remember
The spawn burst observation deserves its own paragraph. While the median hovered near 50 ms, P99 reached 1,027 ms. One tick in a hundred took a full second. Players do not experience your median. They experience the one-second freeze every time a chunk with a large entity population loads, and then they report the server as broken even though the dashboard looks acceptable.
Whenever you evaluate a change, sample the percentiles before and after. If P99 gets worse while the median improves, you have not fixed anything. You have moved the pain.
A Practical MSPT Budget for Real Servers
Numbers pulled from a lab are useless unless you translate them into thresholds you can act on during a live incident. These are the boundaries we recommend, based on the test data above and on what margin a live server needs to absorb saves, plugins, and network jitter.
- Steady-state median under 25 ms: healthy. You have half your budget free for spikes, saves, and player teleports.
- Median between 25 and 40 ms: working but tight. Start profiling before you add content, plugins, or players.
- P95 above 40 ms: investigate now, even if TPS still reads 20. This is the early warning you actually get.
- Median at or above 50 ms: you are at or over the edge. TPS will start dropping with any variance.
- Sustained MSPT above 60 ms: treat as an incident. Players are already experiencing degraded behavior.
One caveat: different server types need different headroom. A creative plot server with a hundred players spread across flat terrain can run hotter than a survival server with redstone farms, because the plot server has less risk of a player building a lag machine. Judge your margin by your worst realistic tick, not your average one.
When MSPT Is High, Do This in Order
The temptation when a server is slow is to change configuration immediately. Resist it. Every config change you make before you know the cause removes one possible explanation and adds one new variable. The order below is deliberate and it costs nothing to follow.
- Measure. Get a median and a P95 from
/tick queryand a spark profile, with realistic player counts. Do not skip this. - Identify the load. In spark, find which tick section dominates: entity ticking, block entities, chunk management, or plugin tasks. Count entities per world and per chunk; Paper and most management plugins can report this.
- Reduce entity load where it matters. Cull wandering mobs outside player view, cap farms, and inspect spawner configurations. Remember that 2,000 villagers is worse than 20,000 NoAI zombies.
- Check plugins and their scheduled tasks. A plugin running a synchronous inventory scan every tick will not show up as vanilla entity cost, and it is a common culprit on servers with heavy economy or minigame stacks. The plugin audit walkthrough covers how to isolate one.
- Only then change configuration. View distance, simulation distance, and entity activation range are powerful, but they are blunt instruments. Applied after diagnosis, they work. Applied before, they just hide the problem.
Two related reads are worth your time once you reach the configuration stage. Simulation distance decides which chunks get random ticks and entity updates at all, and the gap between it and view distance is the single biggest lever most survival servers have; see [View Distance vs Simulation Distance: Cutting Chunk Lag for Real]. If you use loader chunks to keep farms running, the cost accounting is in [Understanding Chunk Loaders and Their Performance Cost]. And if you are still deciding what to run in the first place, [our 2026 server JAR benchmark measures the same tick cost across five server implementations on identical hardware.
For the flags and defaults involved, the Paper configuration reference documents each option with its actual effect, which is worth reading before you copy a tuning guide written for a different Minecraft version.
Pros and Cons of Optimizing by MSPT
Managing a server by MSPT is a discipline, and like any discipline it has trade-offs. Here is an honest accounting.
Pros
- It measures the actual constraint. The main thread is what limits a Minecraft server, so measuring it removes guesswork.
- It converts directly into capacity. At 25 ms steady state you know you have room; at 48 ms you know you do not.
- It makes changes verifiable. Before and after numbers give you a real answer instead of a feeling.
- It separates causes. High MSPT with low CPU points somewhere completely different from high MSPT with high CPU.
- It protects your budget. It stops the reflexive RAM upgrade that fixes nothing.
Cons
- It requires sampling discipline. One reading is worse than no reading, because it feels like evidence.
- It does not see everything. Network latency, client-side rendering, and disk I/O can hurt players while MSPT stays low.
- Median alone is misleading. You need percentiles, which is more work than glancing at a dashboard.
- It is version-sensitive. Absolute numbers move between Minecraft and Paper releases, so compare within a version, not across one.
- It can encourage over-tuning. Chasing 12 ms on an idle test server is time better spent on backups and monitoring.
The balance: watch MSPT and P95 as your primary signal, treat TPS as the output it is, and keep an eye on disk and network as separate concerns. That combination catches nearly everything that actually affects players.
Common Mistakes and Expert Tips
These are the errors we see most often, in roughly the order they cost people time.
- Averaging away the spikes. A 20 TPS report over a minute can hide three one-second freezes. Fix: report P95 and P99 next to the median, always, and compare them before and after any change.
- Testing on an empty world. A fresh superflat world with zero entities will report sub-millisecond MSPT and teach you nothing. Fix: force-load the area you are testing so entities are inside ticking chunks.
- Blaming RAM. Adding memory to a CPU-bound tick loop changes nothing except your invoice. Fix: confirm with a spark profile that GC pauses are actually the cost before touching heap size.
- Measuring during world generation. First-visit chunk generation is far more expensive than steady-state ticking and will dominate every reading. Fix: pre-generate with Chunky, as this test did to 22,801 chunks, then measure.
- Not force-loading chunks. Entities in unloaded chunks cost nothing and will make your load test look artificially good. Fix: set a force-load boundary and confirm the entity count in-game before sampling.
- Changing five settings at once. You will never know which one helped. Fix: one change, one measurement cycle, then decide.
- Ignoring the save cost. Autosave landing on a big world is a 160 to 360 ms tick on this test host. Fix: stagger or throttle saves and avoid scheduling them at peak hours.
- Testing with a plugin stack you do not run in production. Fix: benchmark with your real plugin set, or you are measuring a server you do not operate.
The expert habit underneath all of these is boring and effective: keep a log of MSPT median and P95, entity counts, and player counts on a fixed schedule. After a month you will know what normal looks like for your server, and abnormal will be obvious in seconds instead of hours.
Frequently Asked Questions
MSPT means milliseconds per tick: the wall-clock time the main server thread spends completing one tick. The budget is 50 ms because the server targets 20 ticks per second. Reading MSPT tells you how much of that budget is already spent, which is more useful than TPS alone.
Sustained MSPT at or above 50 ms means ticks are running over budget and TPS will drop. Aim for a steady-state median under 25 ms, investigate when P95 passes 40 ms, and treat 50 ms as the edge.
No, not if the tick loop is CPU-bound. More heap only helps when garbage collection pauses are the cause of the spikes. Check a spark profile for GC time before increasing memory; in most cases entity count and plugin logic are the real cost.
TPS is a rolling average, so short spikes disappear inside it. In our test the median stayed near 50 ms while the 99th percentile hit 1,027 ms. Sample P95 and P99 with the tick query or spark, and check network latency separately, because TPS does not measure that at all.
Conclusion
MSPT and tick rate are not complicated once you separate them. The server has 50 milliseconds per tick, twenty times a second. Every entity, block update, and plugin task shares that budget. MSPT tells you how much of it is gone, TPS tells you what happened when it ran out, and percentiles tell you about the moments players actually complain about.
The test numbers in this guide give you a calibration point: 10,000 simple entities is roughly half a tick budget, 2,000 villagers is more than double it, and a server sitting at 48 ms is one spike away from visible trouble. Use 25 ms as your steady-state target and 40 ms P95 as your investigation trigger, and you will catch problems while they are still cheap to fix.
If your server is already above those lines, start with a measurement pass today: run /tick query ten times at peak, take a spark profile, count your entities, then work the list above in order. For the wider groundwork, our server JAR benchmark and plugin audit guide are the natural next steps. Measure first, change one thing, measure again. That habit will do more for your server than any single configuration flag.

Leave a Reply