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 see | What it is | Where 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.
Read the real numbers
Run these in the panel console or in-game as an op:
tps mspt
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.
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.
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:
# 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.
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.
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:
view-distance=8 simulation-distance=5
| Setting | What it controls | Sensible value |
|---|---|---|
view-distance | How far chunks are sent to players, what they can see | 7 – 10 |
simulation-distance | How far the server ticks mobs, crops and redstone | 4 – 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.
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.
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:
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:
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.
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.
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:
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:
worldborder set 10000
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.
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:
[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:
- Remove plugins you don't use. Every one holds memory whether anyone touches it or not.
- Cut your world count. Each loaded world keeps its own chunks in memory.
- Restart daily: see step 8.
- Upgrade the plan. Sometimes 2 GB is simply not enough for what you're running, and no amount of tuning changes that.
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.
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:
| Cron | Task | Wait |
|---|---|---|
0 5 * * * | Send command say Restarting in 60 seconds | 30s |
Send command say Restarting in 30 seconds | 25s | |
Send command say Restarting now | 5s | |
| 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.