← Blog

Minecraft Server TPS: How Ticks Work and How to Fix Lag

By Benjamin D. · PDG

· 7 min read

Illustration for the article: Minecraft Server TPS: How Ticks Work and How to Fix Lag
Contents

Minecraft server TPS measures how many times per second the game loop processes world logic, and a healthy world holds 20 TPS at all times. When that number drops, players feel it as rubber banding, delayed block breaks, and mobs that freeze mid-air. Tick lag comes from CPU-bound work piling up faster than the loop can clear it, not from network latency.



How Minecraft server TPS actually works

Every world runs on a tick loop that fires twenty times per second, one tick every 50 milliseconds. During each tick the loop processes entity movement, block updates, redstone circuits, mob AI, and any command or plugin logic scheduled for that pass. If everything finishes inside that 50ms window, the console reports a clean 20 TPS.

Once a tick takes longer than 50ms to complete, the loop cannot catch up on the next cycle and starts queuing work. This is what players call lag, even though the connection itself is fine. The metric to watch is MSPT, milliseconds per tick, because TPS alone hides how close the loop actually sits to its ceiling.

A world can display 19.8 TPS while already running dangerously close to the limit, since TPS is capped at 20 and only drops once the damage is visible. MSPT shows the trend earlier, before anyone notices anything in game.

If you manage a modded pack or a large survival world, matching your tick budget to real hardware and memory allocation makes tuning far easier than fighting default settings. The hardware profile behind a Minecraft server hosting plan running Paper, Spigot or Fabric sets the ceiling every optimization step in this guide has to work within.



What causes tick lag in the first place

Tick lag is almost always CPU-bound rather than memory-bound, since a single tick has to run on one thread no matter how many cores the machine has. The main sources are entity counts, redstone activity, chunk generation, and plugin or datapack logic that runs on every tick instead of on a schedule.

Entities and mob farms

Hoppers, item stacks on the ground, and dense mob farms are the most common cause of a slow tick. Each hopper checks its inventory every tick, and a farm with dozens of hoppers stacked together multiplies that cost quickly. Uncapped item drops from a mob grinder can also flood a chunk with entities the loop has to track individually.

Redstone and command blocks

Fast redstone clocks and large command block chains execute on every tick they touch, and a poorly built contraption can hold a chunk busy indefinitely. Repeating command blocks set to always active are a frequent culprit on public worlds where players build without limits.

Plugin and datapack overhead

A plugin that runs a database query, a scoreboard update, or a particle effect on every tick adds fixed overhead regardless of player count. Datapacks with unthrottled function calls behave the same way, and both are easy to miss because they don't show up as an obvious in-game object.



Reading timings reports and spark profiler output

Paper and Spigot builds include a built-in timings report, while the spark profiler works across Paper, Fabric, and Forge and gives more detail on modded packs. Both tools sample what the tick loop spends time on and produce a shareable report link instead of raw console text.

/timings report
/spark profiler --timeout 60
/spark tps
/spark health

The timings report breaks tick time down by plugin and by event type, so a plugin using an outsized share of tick time stands out immediately. Spark goes further and shows a flame graph, which reads from bottom to top: wide bars near the top are where the loop is actually spending its milliseconds.

When reading either report, ignore anything under roughly 5% of total tick time and focus on the two or three heaviest entries. Chasing every small percentage wastes time and rarely moves the needle on the main bottleneck.

What to look for in a flame graph

  • A single plugin or mod consistently above 20% of tick time.
  • Chunk loading or chunk generation appearing during normal gameplay, not just on server start.
  • Entity tracking or hopper transfer methods high in the stack on survival worlds.
  • Garbage collection pauses showing up as sudden spikes rather than a steady load.


Tuning view distance, simulation distance and entity limits

View distance and simulation distance are the two settings with the biggest direct effect on tick time, because every extra ring of loaded chunks adds entity ticking, block updates, and redstone processing. Lowering simulation distance keeps far chunks visible to players without forcing the loop to fully simulate them.

# server.properties
view-distance=8
simulation-distance=6

Paper adds finer control through paper-world-defaults.yml, where per-world entity and mob caps prevent a single overloaded region from dragging down the whole world.

# paper-world-defaults.yml
entities:
  spawning:
    per-player-mob-spawns: true
  entities-target-cap: 0
chunks:
  max-auto-save-chunks-per-tick: 24

On heavily built survival worlds, capping hoppers and item stacking through spigot.yml reduces the hidden cost of farms without banning them outright.

# spigot.yml
world-settings:
  default:
    hopper-transfer: 8
    hopper-check: 8
    item-merge-radius: 4.0


Chunk loading, pregeneration and garbage collection settings

New chunk generation is expensive because it involves world generation math the loop doesn't need for already-generated terrain. Pregenerating a world's border with a plugin such as Chunky before opening it to players removes that cost from live gameplay entirely.

/chunky world world
/chunky radius 5000
/chunky start

Garbage collection pauses are a separate cause of stutter that TPS alone doesn't explain well, since a long GC pause can freeze the whole JVM for a fraction of a second regardless of tick logic. The Aikar's flags JVM arguments are the standard starting point for reducing pause frequency on G1GC.

java -Xms6G -Xmx6G -XX:+UseG1GC \
-XX:+ParallelRefProcEnabled \
-XX:MaxGCPauseMillis=200 \
-XX:+UnlockExperimentalVMOptions \
-XX:+DisableExplicitGC \
-jar paper.jar nogui

Setting -Xms and -Xmx to the same value avoids the loop pausing to resize heap memory mid-session. If you run the JVM yourself through a control panel on a Pterodactyl VPS, these flags usually go in the startup variable field rather than a config file.



A practical checklist to restore stable performance

Work through diagnosis before changing settings blindly, since lowering view distance on a world that is actually redstone-bound won't fix anything.

TPS readingWhat it usually means
19.5 to 20Normal operation, no action needed
17 to 19.5Early strain, check spark before it worsens
10 to 17Active tick lag, isolate the cause now
Below 10Severe overload, restart may be required
  1. Run a spark profile during normal peak hours, not right after a restart.
  2. Identify the two heaviest entries in the flame graph.
  3. Apply the matching fix: entity caps for mob farms, hopper limits for storage systems, view distance for large populated worlds.
  4. Pregenerate remaining terrain instead of letting players trigger generation live.
  5. Confirm Aikar's flags are applied and heap size matches available memory.
  6. Re-run spark to confirm the change actually reduced tick time.

Keep a written log of each change and its effect, since tick lag on a long-running world is often the result of several small issues stacking together rather than one obvious cause. Further reading on plugin-specific tuning is available on the Nexus Games blog.



Conclusion

Fix the actual bottleneck a spark report shows, not the first setting that looks suspicious. Most tick lag traces back to unchecked entity counts or hopper farms rather than raw player numbers, so profile before you lower view distance. Pregenerate terrain, cap entities per world, and confirm GC flags match your heap before touching anything else.



FAQ

Why does TPS drop even when few players are online?

TPS is tied to world activity, not player count. A single automated farm with dozens of hoppers, an active redstone clock, or a chunk full of dropped items can hold tick time high with only one or two players connected, since the loop still has to process every entity and block update each tick regardless of who is watching.

Does adding more RAM fix low TPS?

Extra memory only helps if the world was running out of heap and triggering frequent garbage collection pauses. If the bottleneck is a single-threaded tick loop overloaded by entities or redstone, additional RAM changes nothing, because tick processing speed depends on CPU clock speed and code efficiency rather than available memory.

What is a safe TPS for a survival world with plugins?

Anything consistently at or above 19.5 TPS feels smooth to players and leaves headroom for occasional spikes during events or large builds. Sustained readings below 18 TPS are usually noticeable as rubber banding and delayed interactions, and are worth investigating with a profiler before the world grows and the problem compounds further.

Read next

Minecraft server rental

10,000+ 1-click modpacks

from $8.07/mo

Rent my Minecraft server