Minecraft TPS and server lag: finding the actual cause
Lag is three unrelated problems wearing one word. Most failed fixes start by treating one of them as another: buying RAM for a network problem, lowering view distance for a frame rate problem, opening a host ticket about a hopper array. Work out which one you have first. Everything after that is cheap.
Three problems, one word
| Kind | What is slow | Who feels it | Signature |
|---|---|---|---|
| Server tick lag (low TPS) | The world simulation, on the server | Everyone at once, equally | Mobs stand still then jump several blocks. Furnaces smelt slowly. Blocks break, vanish, then reappear. |
| Network lag (high ping) | The link between one client and the server | One player, or everyone on one route | Your movement rubber-bands, but mobs, furnaces and other players behave normally. |
| Client frame rate (low FPS) | Rendering on the player's own machine | One player | The whole picture stutters, menus included, while the world state stays correct. |
The sixty second test
- Ask in chat. Several people reporting it in the same moment means tick lag. One person alone means their connection or their machine.
- Press F3 and read the fps line. Low fps on a world that otherwise behaves correctly is a client problem, and no server setting will help.
F3then2adds the frame time graph,F3then3adds the ping graph. - Break a block and watch it. On a healthy server it breaks and stays broken. If it breaks, disappears and then pops back, the server did not process your action in time.
- Watch a furnace. One smelting visibly slower than normal is the world itself running behind. Pure network trouble never slows a furnace.
- Run the numbers.
/tpsand/mspton Paper-family servers,/tick queryon modern vanilla,/spark tpsanywhere spark is installed.
Only if step five shows a real tick problem does the rest of this page apply to you.
What TPS actually is
A Minecraft server runs a fixed loop. Twenty times a second it advances the world by one tick: mob AI, block updates, redstone, item movement, hopper transfers, chunk loading, and every line of plugin or mod logic hooked into it. Twenty ticks per second gives each tick a budget of 50 milliseconds.
Finish inside 50ms and the server idles out the remainder and starts the next tick on schedule, so TPS reads 20.0. Take 80ms and the next tick starts 30ms late, and TPS falls. TPS is not a speed dial you can turn up. It is what is left over after the work is done.
Below 20, the world itself runs slow. At 10 TPS everything the server owns moves at half speed: furnaces, crops, brewing stands, mob AI, redstone clocks, hopper lines. Your own walking is largely predicted by your client, which is why you can often sprint around normally on a server that is crawling. That mismatch is why so many reports read as "it feels fine but nothing works". The console line everyone quotes says the same thing in numbers:
The server fell that far behind schedule and skipped ticks to catch up. One of these during a world save or a burst of terrain generation is normal. A console full of them is not.
The part most guides skip: TPS can read fine while ticks are spiking
TPS is capped at 20 and averaged over minutes. A server whose ticks are mostly 15ms but which throws a 300ms tick every second still averages close to 20.0, and players still feel a steady stutter. The honest number is MSPT, milliseconds per tick, and specifically its spread rather than its average.
| Reading | What it means | What to do |
|---|---|---|
| TPS 20.0, MSPT median well under 50 | Healthy, with headroom | Nothing |
| TPS 20.0, MSPT 95th percentile above 50 | Spiky workload. Players report stutter, not slowness. | Hunt the periodic event, not the sustained load |
| TPS 18 to 20 | Small sustained overrun | Usually entity or chunk count creeping upward |
| TPS below 18 | Visibly slow to players | Profile under load. One cause usually explains all of it. |
| MSPT max in the hundreds, median low | A periodic event: collection pause, auto-save, or chunk generation | See the symptom table below |
How to measure it
Built in, no plugins needed
/tick queryprints the target tick rate plus real performance: average time per tick and percentiles. Added in Java Edition 1.20.3, permission level 3, so run it from console or as an operator. Your best built-in reading on plain vanilla./debug startthen/debug stopwrites aprofile-resultstext file into thedebugfolder. Coarse next to spark, but it needs nothing installed./perf startrecords ten seconds and writes a zip intodebug/profiling, dedicated servers only. Inside are per-dimensionentities.csv,chunks.csvandticking.csv. The entity CSV alone tells you how many of what, and where.
Paper-family servers
/tpsgives TPS averaged over the last 1, 5 and 15 minutes./msptgives average, minimum and maximum milliseconds per tick over the last 5, 10 and 60 seconds. Use it to catch spikes that/tpssmooths away./paper entity list [filter] [world]lists ticking entities,/paper mobcapsshows global mob caps,/paper chunkinforeports loaded chunks per world.
spark, the community standard profiler
spark runs on Paper, Spigot, Fabric, Forge and NeoForge, and it is the tool any experienced admin will ask you for.
/spark tpsshows TPS and MSPT together, median and 95th percentile included, colour coded./spark healthopens a live dashboard refreshing every ten seconds;/spark health show --memoryprints heap detail to console./spark profiler start, then/spark profiler stopafter several minutes under real load, produces a shareable flame graph./spark profiler openviews it without stopping,--timeout <seconds>stops it for you,--thread *widens it beyond the main thread./spark tickmonitor --threshold-tick <milliseconds>reports only ticks over a duration you choose. The fastest way to catch an intermittent spike you cannot reproduce on demand./spark pingreports player round trip times, separating network lag from tick lag in one command.
Two rules for any measurement: take it while real players are online and the problem is happening, and let it run for minutes rather than seconds. A profile of an empty server is a profile of nothing. spark's own explainer on TPS and MSPT is worth reading once, and our spark guide covers reading the flame graph.
Symptom to cause
| Symptom | Most likely cause | What to check |
|---|---|---|
| Steady low TPS, same all day | Sustained workload: entity count, loaded chunks, or an always-on plugin task | Five minute spark profile under load, plus /paper entity list * and /paper chunkinfo |
| Freeze every few seconds | Garbage collection pauses, or a short-period scheduled task | Heap usage in /spark health, then the JVM flags guide |
| Freeze every few minutes, regular as a clock | The auto-save, which runs every 6000 ticks by default, exactly five minutes | Save line timestamps in latest.log, then the save tick guide |
| Fine when players group up, bad when they spread out | Each player loads their own chunks, so spreading multiplies the ticked area | /paper chunkinfo, then simulation-distance |
| Spike when someone explores new land | Terrain generation for chunks that never existed before | Chunk loading and pre-generation |
| Started right after adding a plugin or mod | That plugin or mod | Remove it, measure, put it back. A spark profile usually names it in one line. |
| Only one player affected | Their connection or their client, not your server | /spark ping, their F3 ping graph, their fps |
| Only at one location | A local entity pile, a hopper array, or a redstone clock left running | /paper entity list * <world>, then stand there and watch /mspt |
The real causes, in the order they turn out to be
- Entity accumulation. Mobs, dropped items, minecarts, boats, armour stands, loose experience orbs. The usual stories are an AFK mob farm with no kill chamber, a hopper line that overflowed onto the floor, and thousands of items sitting in a chunk nobody has walked through for weeks. Every one of them is ticked. This is the single most common answer.
- Chunk loading. Players spread across the map load several times the chunks that the same players load standing together. Generating brand new terrain is the expensive version of this.
- Redstone and hoppers. Hoppers poll for items on a schedule whether or not anything is moving, so a wall of idle hoppers costs you every tick, and a redstone clock nobody switched off costs you forever. Spigot-family servers expose
ticks-per: hopper-transferinspigot.yml. - One misbehaving plugin or mod. Almost always a scheduled task doing more than intended: a scoreboard rebuilt every tick, a claim plugin scanning the world, a mod walking every inventory.
- View and simulation distance set too high. A radius of 16 covers roughly two and a half times the chunk area of a radius of 10. Plenty of servers run high values purely because a guide said to.
- Garbage collection pauses. A poorly configured heap makes the JVM stop the world periodically, which looks exactly like a mystery freeze. Covered in the Aikar's flags guide.
- Genuinely insufficient hardware. It happens, and it is usually last rather than first. The vanilla tick loop is single threaded, so single core clock speed matters far more than core count; modded loaders add worker threads but still tick the world on one. Before concluding it, get a profile showing the work is legitimate and spread out rather than concentrated in one farm, one plugin or one chunk. See RAM and sizing and modpack hardware sizing.
What to change, cheapest first
simulation-distanceto 6 or 8. Move this first. It controls how far out the server actually ticks entities and blocks, whileview-distancecontrols how far terrain is sent for rendering. Lowering simulation alone cuts tick work without making the world look smaller. Both default to 10 and accept 3 to 32.view-distanceto 8 or 10 if you are above that. Players do notice this one, which is why it comes second.entity-broadcast-range-percentagedown from its default of 100 toward 75 or 50. It sets how close entities must be before they are sent to clients: a bandwidth and client-side win more than a tick win, but free.- Clear the entities you found, and stop them returning. A kill chamber on the farm, a chest terminating the hopper line, and on Spigot-family servers the
merge-radiusandentity-activation-rangesettings inspigot.yml. - Pre-generate the area players actually use so exploration stops paying for worldgen mid-session. See the pre-generation guide.
- Fix the heap size and JVM flags. Aikar's flags.
- Then, and only then, more or faster hardware.
Every server.properties key above is described in the server.properties reference, and changes there need a full restart, not a reload. If you are still on an unmodified vanilla jar, moving to a Paper-family build is usually worth more than any single setting here; the server software comparison covers the trade-offs.
What will not fix it
- Adding RAM to a tick-bound server. Memory cures out-of-memory crashes and long collection pauses. It does not shorten a tick that is 90ms of mob AI and hopper polling. If MSPT is high while the heap sits at 40 percent used, more memory changes nothing. RAM and sizing covers what memory does fix.
- Restarting on a timer. It resets the symptom and buys a few hours, and it destroys your best diagnostic. A server that is fine for two hours and then degrades every single time is telling you something is growing; a scheduled restart deletes that evidence before you can read it.
- Setting
max-tick-time=-1. That disables the watchdog which kills a hung server. Ticks are exactly as slow afterwards: you removed the alarm, not the fire. Heavy modpacks do sometimes raise it legitimately, but nobody ever fixed lag with it. - Opening a host ticket before measuring. If you do need one, send the spark profile link, your
/msptoutput and the timestamps of the worst spikes. "Server is laggy" earns you a ping test. A profile earns you an answer.
If the lag ends in a crash rather than a slow tick, that is a different read: start with the crash log guide instead.
Looking for managed Minecraft server hosting? Supercraft runs Minecraft dedicated servers with daily backups, instant setup, and 4 region options.