← Blog

Understanding Minecraft Server TPS: What Makes Your World Lag and How to Fix It

By Benjamin D. · PDG

· 9 min read

Illustration for the article: Understanding Minecraft Server TPS: What Makes Your World Lag and How to Fix It
Contents

Minecraft server TPS is the number of game ticks your world manages to process each second, and 20 is the hard ceiling. Below that, mobs walk in slow motion, hoppers stall and redstone clocks drift. Tick loss almost always traces back to a short list of causes: chunk loading pressure, entity crowds, redstone loops, mob farms and an oversized view distance.



How a tick works and why 20 is the ceiling

A Minecraft world advances in discrete ticks, and the engine targets 20 per second. Each tick gets a 50 millisecond window to update mob AI, redstone, block updates, fluid flow, chunk loading and player movement. Finish early and the main thread idles until the next tick. Overrun that window and the tick rate slips under 20, which players read as world lag.

MSPT (milliseconds per tick) is the more actionable figure. Tick rate stays pinned at 20 until MSPT crosses 50, so a world averaging 45 MSPT looks perfectly healthy while sitting one mob farm away from stuttering. Track MSPT first, tick rate second.

Client frame rate is a separate problem. A player at 25 FPS with the world running at 20 ticks has a GPU or render distance issue, not a tick problem. Broken block animations, delayed chest openings and mobs that slide instead of walking point at the world thread.

Average MSPTTick rateWhat players notice
Under 3020Nothing
30 to 4520 but fragileBrief hitches during raids or explosions
50 to 7014 to 18Slow block breaking, laggy mob movement
Above 100Under 10Rubber-banding, item pickup delays, farm output collapse

When every configuration switch has been tuned and MSPT still climbs, the machine itself becomes the limit: single-thread throughput, memory bandwidth and disk latency decide how much a world can chew through per tick. That is exactly what Minecraft server hosting on Ryzen 9 7950X3D with DDR5 ECC memory and NVMe storage is built to sustain.



Measuring lag with in-game diagnostic tools

Guessing wastes hours. Every serious diagnosis starts with a profiler that names the exact task eating milliseconds.

Quick readouts from the console

Paper and its forks answer instantly, and recent vanilla builds expose their own tick command. Run these from the live console in your panel or in chat with operator rights.

/tps
/mspt
/tick query
/spark tps
/spark health

The log line Can't keep up! Is the server overloaded? Running Xms behind confirms the main thread missed its window. One occurrence after a world save is normal, a repeating pattern is not.

Profiling with spark

Spark samples the main thread and produces a call tree showing which plugin, entity type or block entity consumes the time. Start a capture while the lag is happening, not afterwards.

/spark profiler start --timeout 300 --thread "Server thread"
/spark profiler stop
/spark heapsummary
/spark entities

The /spark entities output ranks entity types by count per world. If a single chunk holds hundreds of items or villagers, you have found your answer without reading a single stack trace.

Locating the guilty chunks

Once a culprit type is known, find its coordinates. Paper exposes chunk debugging, and most administration plugins can teleport you straight to the densest cluster. Trimming the source beats raising limits.

/paper mobcaps
/paper dumpitem
/minecraft:debug start
/minecraft:debug stop


What makes Minecraft server TPS drop

Five families of workload account for the overwhelming majority of tick loss on player-driven worlds.

Chunk loading and terrain generation

Generating new terrain is the single heaviest operation the world thread performs. A player sprinting on an elytra across unexplored land forces continuous generation, structure placement and light calculation. Pre-generating the map with a chunk generation plugin, then keeping exploration inside known borders, removes that spike permanently.

Nether portals multiply the effect: each portal traversal loads a fresh region in another dimension. A world border set on all three dimensions caps how far that can go.

Entity crowds and mob farms

Every loaded entity gets AI, collision and pathfinding work each tick. Villager breeders, iron farms and mob grinders concentrate hundreds of entities into a handful of chunks, and item stacks from an unattended farm accumulate until the chunk becomes a tick sink.

  • Villagers are the most expensive common mob because of their profession and gossip logic.
  • Item entities are cheap individually and lethal in the thousands.
  • Mobs stuck against walls run pathfinding attempts constantly and never resolve.
  • Minecarts with hoppers tick container logic on top of entity logic.

Redstone loops and hoppers

Redstone updates propagate recursively, and a fast clock left running in a loaded chunk burns milliseconds twenty times a second forever. Hopper chains are worse: each hopper polls the container above it on a fixed schedule whether or not items exist.

Replacing long hopper lines with water streams and droppers, and gating clocks behind observers or player presence, usually returns several MSPT on a busy survival world.

View distance and simulation distance

View distance controls how many chunks are sent to clients. Simulation distance controls how many chunks actually tick mobs, crops and redstone. The second one drives the workload, and it multiplies with player count: ten players at simulation distance 10 is a far heavier load than two players at 16.

Plugins, datapacks and scheduled tasks

A plugin that runs a repeating task every tick, scans a region synchronously or writes to a database on the main thread will show up clearly in a spark profile. Datapacks with per-tick function loops behave the same way and are easy to overlook.



Tuning configuration files to reclaim milliseconds

Configuration changes deliver the fastest measurable gains. Apply them one group at a time and re-measure MSPT after each restart, otherwise you never learn which change worked.

server.properties

view-distance=8
simulation-distance=6
entity-broadcast-range-percentage=75
max-tick-time=60000
sync-chunk-writes=false
network-compression-threshold=256

Dropping simulation distance from 10 to 6 typically cuts ticked chunks by more than half. Keep view distance slightly higher so the horizon still looks correct to players.

spigot.yml

entity-activation-range:
  animals: 16
  monsters: 24
  raiders: 48
  misc: 8
  water: 12
  villagers: 16
merge-radius:
  item: 3.5
  exp: 4.0
ticks-per:
  hopper-transfer: 8
  hopper-check: 8

Activation range decides how far from a player an entity keeps running full AI. Beyond it, mobs freeze until someone approaches. Merge radius collapses nearby dropped items into single stacks, which is the cheapest way to survive an overflowing farm.

paper-world-defaults.yml

entities:
  spawning:
    per-player-mob-spawns: true
    despawn-ranges:
      monster:
        hard: 96
        soft: 28
collisions:
  max-entity-collisions: 2
hopper:
  disable-move-event: true
tick-rates:
  mob-spawner: 2
  container-update: 3
  grass-spread: 4
chunks:
  max-auto-save-chunks-per-tick: 8

Per-player mob spawning distributes the mob cap fairly instead of letting one AFK farm consume it globally. Disabling the hopper move event is safe unless a plugin explicitly listens to it. The full key reference is documented upstream: Source.



Memory, garbage collection and single-thread throughput

Long garbage collection pauses look exactly like tick lag: everything stops for 300 milliseconds, then resumes. Oversized heaps make it worse, not better, because a larger heap takes longer to sweep. A survival world with a handful of plugins runs comfortably in 4 to 6 GB; a heavy modpack usually needs 8 GB or more.

java -Xms8G -Xmx8G \
  -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 \
  -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC \
  -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 \
  -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 \
  -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 \
  -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 \
  -jar paper.jar nogui

Set -Xms equal to -Xmx so the heap never resizes mid-game. Use a recent Java runtime matched to your Minecraft version, since newer releases ship meaningful garbage collector improvements.

The world thread remains largely single-threaded, so raw per-core speed matters more than core count. Chunk saving and region file reads are disk-bound, which is where NVMe storage separates a smooth autosave from a visible freeze. Other titles across All our game servers face the same single-thread reality.



A weekly routine to keep the world at 20 ticks

Tick health degrades slowly as players build. A short recurring check catches regressions before anyone complains in Discord.

  1. Run /spark health and note average MSPT at peak population.
  2. Run /spark entities and inspect any entity type above a few hundred.
  3. Check the log for repeated overload warnings and match their timestamps against events.
  4. Verify autosave and backup schedules do not overlap peak hours.
  5. Update the server software and plugins, then re-measure after two days of play.

Rules that prevent lag instead of fixing it

  • Cap farm size in your community rules, and enforce it with a claims plugin.
  • Set a world border on overworld, nether and end.
  • Limit mob and item stacking with a clear announced schedule before any cleanup task.
  • Keep automatic backups active so an aggressive optimisation can be rolled back.

Scheduling restarts once every 12 to 24 hours also clears accumulated memory fragmentation and stray entities. More administration walkthroughs are collected on the Nexus Games blog.



Conclusion

Start with simulation distance and entity counts, in that sequence: those two settings recover more milliseconds than every Java flag combined. Profile before you change anything, apply one modification per restart, and record MSPT each time. The mistake to avoid above all is throwing memory at the problem: a 16 GB heap on a survival world lengthens garbage collection pauses and hides the real culprit, which is almost always a farm nobody wanted to touch.



FAQ

Why do players report lag when the tick rate stays at 20?

That is a network or client issue, not a world issue. Check player ping with the tab list: latency above 150 ms produces rubber-banding while the world ticks perfectly. On the client side, a high render distance, shader packs or insufficient allocated memory cause frame drops that feel identical to tick loss. Ask the player for their F3 screen before investigating anything server-side.

Can too many plugins lower the tick rate?

Plugin count matters far less than plugin behaviour. Thirty well-written plugins can be lighter than one that runs a synchronous region scan every tick. Profile with spark, sort the call tree by self time, and you will see exactly which plugin owns the milliseconds. Common offenders are anti-cheat modules, dynamic map renderers running on the main thread, and land protection plugins recalculating claims too often.

What happens to farms and hoppers when the tick rate falls?

Everything slows proportionally. At 10 ticks per second, hoppers transfer at half speed, crops grow at half rate, mob spawners fire half as often and redstone clocks run twice as slow. Farm output drops accordingly, which is why players usually notice tick loss through reduced production before they notice movement stuttering. Rates return to normal automatically once the tick rate recovers.

Read next

Minecraft server rental

10,000+ 1-click modpacks

from $7.55/mo

Rent my Minecraft server