← Blog

Understanding Minecraft Server TPS: Why Your World Lags and How to Fix It

By Benjamin D. · PDG

· 8 min read

Illustration for the article: Understanding Minecraft Server TPS: Why Your World Lags and How to Fix It
Contents

Minecraft server TPS is the number of game ticks your world manages to process every second, and 20 is the hard ceiling: fall under it and time itself slows down for everyone connected. Drops almost always trace back to a short list of suspects: loaded entities, chunk generation, redstone, view distance and raw single-thread CPU speed. Here is how to measure, isolate and repair each one.



What Minecraft server TPS actually measures

The game loop runs on a fixed schedule: one tick every 50 milliseconds, 20 ticks per second. If the work fits inside that 50 ms window, the loop sleeps the remainder and TPS stays at 20. If the work overruns, the next tick starts late and TPS falls. The number never goes above 20 on a vanilla loop.

Everything the world does happens inside that tick:

  • mob AI, pathfinding and spawning
  • redstone updates and block ticks (crops, fire, fluids)
  • hopper and container transfers
  • chunk loading, saving and lighting
  • player movement validation and inventory logic
  • plugin and mod event handlers

Most of that work sits on a single thread. Modern Paper and Fabric builds push chunk generation, I/O and network packets onto other threads, but the main loop stays serial. That is why a 16-core machine with a slow clock behaves worse than a 8-core machine with a fast one.

TPS is not client FPS. A player with 15 FPS on an old laptop is a client problem. Every player seeing mobs teleport, water flowing in slow motion and blocks taking two seconds to break is a tick rate problem.



Reading MSPT: averages, medians and lag spikes

TPS alone hides the truth because it is capped. A world at 20 TPS with 48 ms per tick is one hopper array away from collapse, and looks identical to a world at 12 ms. The metric that matters is MSPT (milliseconds per tick).

/tps
/mspt
/spark tps
/spark health --upload

On Paper, /tps returns three averages (1 minute, 5 minutes, 15 minutes). A low 1m value with healthy 5m and 15m values means a spike, not chronic overload. Spikes are usually chunk generation, a world save or a plugin task. Chronic drops are structural.

Average MSPTInterpretationWhat to do
Under 25 msComfortable headroomNothing
25 to 40 msStable, but fragile at peak populationProfile during rush hours
40 to 50 msTPS still shows 20, spikes already feltTrim entities and distances
Above 50 msTPS below 20, the world runs slowProfile immediately

When MSPT stays high with no obvious in-world culprit, the machine underneath becomes the limiting factor: single-thread clock, memory latency and disk speed. The hardware behind each instance is listed on our Minecraft server hosting page.



Five common causes of tick loss

Entity count

Entities are the number one killer. Every item on the ground, every mob in a farm, every armour stand, every minecart and every villager gets ticked. A hundred villagers in a trading hall run pathfinding and gossip logic on the main thread every single tick.

/spark profiler start --timeout 120
/minecraft:kill @e[type=item]
/paper entity list

Chunk loading and generation

Generating fresh terrain is the most expensive single operation in the game. A player flying an elytra over unexplored land forces continuous generation, lighting and disk writes. Nether portals and chunk loaders keep far-away areas ticking long after players leave.

Redstone and hoppers

Clocks, observer loops and long hopper chains generate thousands of block updates per tick. A single 0-tick farm left running while its owner is offline can eat half the tick window. Hopper item transfer checks are especially heavy because they poll containers constantly.

View distance and simulation distance

View distance controls how many chunks are sent to clients; simulation distance controls how many are actually ticked. Both scale quadratically: going from 10 to 12 does not add 20 percent of work, it adds far more. Simulation distance is the one that drives mob and redstone load.

Single-core speed and plugin overhead

Since the loop is serial, the clock speed and cache of one core define your ceiling. Add a badly written plugin doing SQL queries or file reads inside a PlayerMoveEvent, and you multiply that penalty by every movement packet received.



Profiling a laggy world with spark

Guessing is a waste of time. The spark profiler samples the main thread and tells you exactly which class, plugin or world consumes the milliseconds. It works on Paper, Fabric, Forge and Velocity, and it produces a shareable web report.

/spark profiler start --timeout 300 --thread * --interval 4
/spark profiler stop
/spark tickmonitor --threshold 100
/spark heapsummary

Run the profiler during the moment the problem happens, not two hours later on an empty world. Five minutes at peak population is worth more than an hour overnight. Read the report top-down: the largest self-time entry is your target. The spark documentation explains how to read the call tree.

For memory issues, /spark heapsummary reveals what fills the heap. Thousands of ItemEntity or TextDisplay objects point straight at a farm or a hologram plugin. Frequent full garbage collections show up as recurring spikes in tickmonitor.

On worlds without spark installed, Paper timings remain a fallback, but the sampled profiler gives far more precise attribution. Install spark first, diagnose second, edit configuration third.



Configuration changes that restore 20 ticks per second

server.properties

view-distance=8
simulation-distance=5
max-tick-time=60000
network-compression-threshold=256
sync-chunk-writes=false

Dropping simulation distance from 10 to 5 typically removes more load than any other single edit, and players rarely notice because view distance keeps the horizon visible.

spigot.yml

spawn-limits:
  monsters: 40
  animals: 8
  water-animals: 3
  ambient: 1
entity-activation-range:
  animals: 16
  monsters: 24
  raiders: 48
  misc: 8
merge-radius:
  item: 3.5
  exp: 4.0
ticks-per:
  hopper-transfer: 8
  hopper-check: 8

paper-world-defaults.yml

chunks:
  max-auto-save-chunks-per-tick: 8
entities:
  spawning:
    per-player-mob-spawns: true
collisions:
  max-entity-collisions: 2
hopper:
  disable-move-event: true
tick-rates:
  mob-spawner: 2
  container-update: 3

Enable per-player-mob-spawns before touching anything else: it stops one AFK player in a mob farm from consuming the global mob cap. Paper's tuning reference is documented in the official PaperMC documentation.

JVM flags and heap sizing

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:InitiatingHeapOccupancyPercent=15 \
 -jar paper.jar nogui

Set -Xms equal to -Xmx. An oversized heap makes garbage collection pauses longer, not shorter, so a modded world with 12 GB allocated can tick worse than the same world with 8 GB and tuned G1GC flags.



Hardware limits: single-thread clock, memory and disk speed

Once configuration is clean and spark shows the time going into vanilla world ticking, you have reached the hardware ceiling. Java's main loop cannot be split across cores, so the metric that matters is per-core performance and cache size, not core count.

Chips like the Ryzen 9 7950X3D help here specifically because of their large L3 cache: chunk and entity data stay closer to the core, which shortens each tick. DDR5 ECC memory reduces latency on the constant allocation churn the JVM produces, and NVMe storage keeps region file writes off the critical path.

Shared cores are the other trap. If several instances fight for the same physical core, your MSPT graph will show random spikes that no profiler can explain, because the time is spent outside your process. Cores reserved for a single instance remove that noise entirely.

Network capacity is rarely the tick problem: 1 Gbit/s of throughput and anti-DDoS filtering applied by default keep packet floods away from the netty threads, but they do not change how fast a redstone clock is evaluated. You can see the full catalogue on All our game servers.



A maintenance routine that keeps the loop stable

  1. Pre-generate the map with Chunky before opening a new world, so exploration never triggers live generation.
  2. Schedule a daily restart during low activity to reset heap fragmentation and clear leaked entities.
  3. Run /spark health weekly and archive the report, so you can see drift over time.
  4. Audit entity counts per chunk after every major build project.
  5. Keep automatic backups enabled and verify one restore per month.
  6. Update Paper or Fabric builds regularly: tick optimisations land constantly.
/chunky world world
/chunky radius 3000
/chunky start
/chunky progress

Run pre-generation while nobody is connected. It will hammer the CPU and disk on purpose, which is exactly what you want it doing at 4 a.m. rather than while thirty players explore.

Document every configuration change with the MSPT value before and after. Without that log you will end up reverting a fix that worked. More administration walkthroughs are published on the Nexus Games blog.



Conclusion

Do not throw memory at a slow tick loop: it is the reflex that fixes nothing and often makes garbage collection pauses worse. Profile first with spark, then cut simulation distance and entity activation ranges, then rebuild the farms the report incriminates. If vanilla world ticking still fills the 50 ms window on a clean configuration, the limit is per-core CPU performance, and only faster cores will lift it.



FAQ

Does adding more RAM increase Minecraft server TPS?

Only up to the point where the heap stops overflowing. Beyond that, extra memory does nothing for tick speed and can hurt it, because a larger heap means longer garbage collection pauses that show up as stutter. Allocate what the world genuinely needs, set the minimum and maximum heap to the same value, and tune G1GC flags instead.

Can a Minecraft world run faster than 20 TPS?

Not in normal play. Vanilla caps the loop at 20 ticks per second and extra headroom is spent sleeping. Recent versions expose /tick rate for operators, and mods such as Carpet allow custom rates, but raising it breaks timing-dependent farms, redstone circuits and mob spawning behaviour. Treat 20 as a target to maintain, never a number to exceed.

Why do players rubber-band while TPS stays at 20?

That is a network symptom, not a tick symptom. Packet loss, high latency on the route or a saturated uplink causes position desync while the world ticks perfectly. Check player ping in the tab list, test with mtr from the client side, and lower network-compression-threshold if many players connect over long distances.

Read next

Minecraft server rental

10,000+ 1-click modpacks

from $7.55/mo

Rent my Minecraft server