HomeGuidesPerformanceFixing lag & low TPS
Guide Performance Paper

Fixing lag & low TPS

How to tell server lag from your own connection, find what is eating your ticks, and tune it back to 20 TPS.

1

Work out whose lag it actually is

"The server is lagging" covers three completely different problems with three different fixes. Sort out which one you have before changing anything.

What you seeWhat it isWhere to look
Blocks break then reappear, mobs stutter, everyone affected at once Server lag: low TPS This guide
High ping, rubber-banding, only some players Network lag Their connection, or the route to the node
Low FPS, choppy camera, but blocks break instantly Client lag That player's own PC and render distance

A quick tell: if you break a block and it comes back a second later, that's the server. If the world is smooth but your framerate is bad, that's your computer.

2

Read the real numbers

Run these in the panel console or in-game as an op:

Console
tps
mspt
Output
TPS from last 1m, 5m, 15m: 14.21, 16.80, 19.94
Server tick times (avg/min/max) from last 10s:
68.4/12.1/191.7

How to read it

  • TPS: ticks per second. 20 is the ceiling; the server can never go faster. Below 18 is noticeable, below 15 is bad.
  • MSPT: milliseconds per tick, and the more useful number. A tick has a 50 ms budget. Under 40 ms is healthy. Over 50 ms means the server can no longer keep up and TPS starts dropping.
Watch MSPT, not TPS

MSPT tells you how close to the edge you are before TPS falls. A server sitting at 20 TPS with 46 ms ticks is one busy evening away from lagging, TPS will still say everything is fine right up until it isn't.

Also glance at the panel's Memory graph. If it's pinned at the top of your plan and staying there, you're looking at a memory problem rather than a tick problem, jump to step 7.

3

Profile it with Spark, don't guess

Guessing at lag wastes hours. Spark measures it. Drop the jar in plugins/, restart, then run a profile while the server is actually lagging:

Console
# sample for 60 seconds, then stop and get a link
spark profiler start --timeout 60

# what is eating memory
spark heapsummary

# which entities are the problem, and where
spark tps

Spark prints a URL to an interactive flame graph. Open it and look at the widest bars, the plugin or system taking the most tick time is right there by name, no interpretation needed.

Profile at the worst moment

A profile taken on an empty server at 6am tells you nothing. Run it when players are on and the lag is happening, or the numbers won't include the thing you're hunting.

4

Turn down the distance settings

This is the biggest single lever, and it's free. Every chunk in view distance is chunk the server has to keep loaded, tick and send to players. Open Files → server.properties:

server.properties
view-distance=8
simulation-distance=5
SettingWhat it controlsSensible value
view-distanceHow far chunks are sent to players, what they can see7 – 10
simulation-distanceHow far the server ticks mobs, crops and redstone4 – 6

Simulation distance is the expensive one. Dropping it from 10 to 5 cuts the ticked area to a quarter and players barely notice, because everything nearby still behaves normally.

Careful

Setting simulation-distance below 4 breaks things players will complain about: mob farms stop producing and crops stop growing while they stand next to them. Don't go under 4.

Restart for these to take effect.

5

Get the entity count under control

Mobs are the usual answer. Run spark tps or look at the entity counts in your profile, a few thousand of something in one chunk is a farm, and it will be costing you more than everything else combined.

Cap what can spawn

Open Files → bukkit.yml:

bukkit.yml
spawn-limits:
  monsters: 35      # default 70
  animals: 8        # default 10
  water-animals: 3
  ambient: 1

ticks-per:
  monster-spawns: 4  # spawn attempts less often
  autosave: 6000

Stop distant entities from ticking

Open Files → spigot.yml:

spigot.yml
world-settings:
  default:
    entity-activation-range:
      animals: 16
      monsters: 24
      misc: 8
    merge-radius:
      item: 3.5
      exp: 4.0
    item-despawn-rate: 4000
    max-entity-collisions: 2

merge-radius is the quiet win here: dropped items within that radius get stacked into one entity, so a mob farm spitting out hundreds of drops becomes a handful of objects instead.

Find the hotspot

EssentialsX has /entitycount, and Spark's profile shows you the chunk coordinates. Fly there, it's nearly always one player's farm, and a quiet word is faster than any config change.

6

Pre-generate your world

Generating new terrain is one of the most expensive things a server ever does. If your lag spikes when someone explores or runs an elytra across fresh land, this is why, and it's completely avoidable.

Install Chunky, then generate the area you expect players to use, once, while nobody is on:

Console
chunky world world
chunky radius 5000
chunky start

# check on it later
chunky progress

Pair that with a world border at the same radius so players can't wander past the pre-generated area:

Console
worldborder set 10000
It gets big

A 5,000-block radius is roughly 10–15 GB on disk, and generating it will peg your CPU for a while. Run it overnight, and check your plan has the storage before you start.

7

Check whether it's actually memory

If the panel's memory graph sits at the top of your plan and the server freezes for a second or two at regular intervals, that's garbage collection thrashing, not tick load. Tuning entities won't help.

Look for this in the console:

Console
[14:22:10 WARN]: Can't keep up! Is the server overloaded?
Running 4218ms or 84 ticks behind
[14:22:14 ERROR]: java.lang.OutOfMemoryError: Java heap space

What actually helps, in order:

  1. Remove plugins you don't use. Every one holds memory whether anyone touches it or not.
  2. Cut your world count. Each loaded world keeps its own chunks in memory.
  3. Restart daily: see step 8.
  4. Upgrade the plan. Sometimes 2 GB is simply not enough for what you're running, and no amount of tuning changes that.
Startup flags

Your servers already run tuned Aikar flags for garbage collection out of the box, so there's nothing to add there. If you've pasted custom flags into the Startup tab from a forum post, they're most likely making things worse, put it back to the default.

8

Restart on a schedule

Long-running servers accumulate memory that plugins never hand back. A daily restart clears it and takes twenty seconds. Set it up under the Schedules tab:

CronTaskWait
0 5 * * *Send command say Restarting in 60 seconds30s
Send command say Restarting in 30 seconds25s
Send command say Restarting now5s
Restart server-

Pick the quietest hour you have. 5am local time is a safe default for most communities.

Troubleshooting

TPS is 20 but everything still feels laggy

That's not server lag. Ask a player for their ping (/ping with EssentialsX), over 150 ms and it's the network between them and the node. If ping is fine too, it's client-side: have them turn their own render distance down and check their framerate.

"Can't keep up! Is the server overloaded?" fills the console

The message means a tick took far longer than 50 ms. On its own it's a symptom, not a cause, occasional lines during world generation or a backup are normal. Constant ones mean you should profile with Spark (step 3). Ignore any advice to "disable the warning"; it's telling you the truth.

Lag only starts when a certain player joins

Nearly always a farm or a redstone contraption in their base. Profile while they're online, look at the chunk coordinates Spark reports, and go take a look. Common culprits: hopper chains under item farms, chunk loaders, and an iron farm built five times over.

It lags for a few seconds every few minutes, then recovers

That rhythm usually means autosave or a scheduled task. Raise ticks-per.autosave in bukkit.yml to 6000 (five minutes), and check your Schedules tab for anything running on a tight loop. Backups also cause a brief pause, move them to a quiet hour.

I've tried everything and it's still slow

Run spark profiler start --timeout 120 during the lag and send us the link in a ticket. That single URL tells us more than any description could, and it's the fastest way to a real answer.

None of these fixed it? All support runs through tickets on our website. Include your server ID and a Spark profile link, it saves a lot of back and forth.
Open a ticket
Was this guide helpful?