Players are complaining, so you want to know how to reduce Minecraft server lag. First step: figure out which kind of lag you have. Fixing the wrong one is how people burn a weekend.
The short version: run /spark tps. If TPS sits below 20, it's server lag, and everyone feels it. Fix it in this order: lower view and simulation distance, run Paper, pre-generate the world, tame entity and redstone farms, profile with spark to find the plugin or contraption eating the tick, then look at RAM and the host's CPU. Change one thing at a time and re-check after each.
Why is my Minecraft server so laggy? Server, network or FPS
A Minecraft server runs a loop 20 times a second. That's 20 TPS (ticks per second), so each tick has to finish in 50 milliseconds or less. When ticks run long, the server can't keep up. MSPT is the average milliseconds per tick. If some ticks run over 50 ms and only 16 finish in a second, you get 16 TPS. Blocks take a beat to break, mobs stutter, and everything rubber-bands for everybody.
| What you see | Likely cause | First check |
|---|---|---|
| Everyone lags, blocks reappear, mobs stutter | Server lag (low TPS, high MSPT) | /spark tps |
| High ping for one player, TPS is fine | Network latency | /spark ping --player <username> |
| Choppy picture but the world responds normally | Client FPS | Your own game, not the server |
That table is how I read the numbers. "Lag only for me" is almost never the server. "Lag for everyone" almost always is.
spark's /spark tps prints TPS and CPU usage, /spark ping gives the average player round-trip ping, and /spark health builds a report with TPS, CPU, memory and disk. Healthy is 20 TPS. spark colours its numbers green, amber and red, so you can see trouble at a glance. spark comes bundled with Paper. On Fabric or Forge you add it as a mod.
One more sign of bad lag: the vanilla server has a watchdog, max-tick-time, which defaults to 60000 ms. If a single tick takes longer than that, the server stops itself. Paper's "server has not responded for 10 seconds" thread dump is the same idea. It's not a bug report, it's a tick that took far too long. Read the top of the stack trace, and look for plugin names.
Lower view distance and simulation distance
The cheapest fix and often the biggest. In server.properties on Java, view-distance and simulation-distance both default to 10 chunks (as of Java 26.3), measured as a radius around each player. View distance is how far chunks get sent. Simulation distance is how far from players living entities get updated. Outside that radius they aren't ticked at all. The wiki's own advice is to reduce them if players have major lag. Both can go from 3 to 32.
I won't hand you a magic number, because it depends on your hardware and your players. Do it stepped: drop both by a couple of chunks, restart (server.properties changes need a restart), play for a while and re-check /spark tps. Still bad? Drop again. Fine now? Stop there and leave it. More on these settings in my server.properties walkthrough.
Two related settings. entity-broadcast-range-percentage defaults to 100, and higher values make entities render from farther away, potentially causing more lag. Lowering it to 50 halves the distance. And on Paper you can override view and simulation distance per world in spigot.yml under world-settings.
Running Bedrock? As of Bedrock 1.26.63.1, the dedicated server has view-distance (default 32) and tick-distance (default 4, range 4 to 12), and the wiki says higher values on both hurt performance. Same stepped approach.
Run Paper instead of vanilla
If you're on the vanilla server jar, switching to Paper is the biggest single step after distances. Paper is built on Spigot and adds a pile of performance settings, plus spark built in. Most of the fixes in the rest of this guide are Paper settings. It can't copy vanilla behaviour 100%, so test your farms after switching. The full rundown of your options, including the other forks, is in my server software comparison.
Pre-generate the world with Chunky
Generating brand-new terrain is expensive, and it happens right when a player sprints into unexplored land. Pre-generating means doing that work ahead of time, before players are on. Chunky is the usual tool. It runs on Spigot, Paper, Fabric, Forge, NeoForge and Sponge.
chunky radius 5000chunky start
For the Nether, run chunky world world_nether first, then chunky start. World names vary by setup. chunky progress shows how it's going, and chunky pause and chunky continue do what they say. Type them as shown in the console. In-game, put a slash in front.
Chunky's own docs say big worlds eat a lot of disk and take a long time, so if you're unsure, start with a smaller radius like that 5000 and extend later. Check the ETA, and turn off map plugins while it runs. Set a world border so players can't wander past what you generated.
Pre-generation only fixes lag from loading new chunks. It does nothing for a lag machine you built inside the world.
Entities, farms and redstone
Mob farms, hopper chains, item sorters and redstone clocks are the classic culprits. A lot of entities ticking in one place is expensive. If your lag starts after somebody builds a giant farm, believe it, then prove it with spark (next section).
Paper gives you dials. The ones worth knowing:
- Entity activation range in
spigot.yml. Entities outside it tick less often. Defaults are 32 for animals, monsters and villagers, 64 for raiders, 16 for water mobs and misc (dropped items count as misc). - Armor stands:
entities.armor-stands.tickin the world config. Paper says turning it off can help if you have lots of them. - Pathfinding:
misc.update-pathfinding-on-block-update. Paper says disabling it can improve performance significantly, and recommends that with lots of loaded entities, automated farms or redstone clocks. - Explosions:
environment.optimize-explosionsis off by default and speeds explosions up significantly. - Hoppers:
hopper.disable-move-eventimproves hopper performance dramatically, but it breaks protection plugins and anything else that listens to that event. I'd leave it alone unless hoppers are your proven problem. - Redstone:
misc.redstone-implementationisVANILLAby default.ALTERNATE_CURRENTandEIGENCRAFTcan greatly reduce redstone dust lag, but they change how dust behaves, so some contraptions can break.
Don't paste a random "optimized" config from the internet. Paper itself says that if farms, redstone or spawning start acting strange after copying one, revert to defaults. Change one setting, test, move on.
Profile with spark and find the real culprit
Guessing is slow. A profiler shows what the server is actually spending its tick on. On Paper:
/spark profiler start --timeout 300runs a five-minute profile. Do it while the lag is happening.- For spikes only,
/spark profiler start --only-ticks-over 100 --timeout 300records just the ticks over 100 ms. /spark profiler stopends it early and opens the results.
Open the report and look for what sits high in the tick: a plugin name, an entity type, a chunk-loading routine. Add --alloc if you suspect memory allocation instead of CPU. /spark tickmonitor --threshold-tick 100 reports only ticks over a given length, handy for catching spikes you didn't see coming.
Plugins and mods as the culprit
If the profile points at a plugin, or you can't read the profile, bisect. Paper's own advice:
- Rename the
pluginsfolder toplugins-disabledand start the server. If the lag is gone, a plugin is the cause. - Put half the plugins back (rename a jar to
.jar-disabledto switch it off) and test. - Repeat with the half that brings the lag back.
Keep dependencies together. Library plugins like ProtocolLib or Vault providers and your permission plugin will break whatever depends on them if you disable them alone. Also check for plugin updates first, libraries included. If you're picking plugins, my plugin roundup is a place to start, and here's how to install them properly. Modded servers get the same treatment: profile, then bisect the mod list.
RAM: more isn't automatically better
High RAM use on its own isn't a problem. Java grows its heap up to the maximum you set, so a full-looking meter is normal. It matters if you see out-of-memory crashes or bad garbage-collection times. /spark gc, /spark gcmonitor and /spark health show --memory show you that. A crash with no useful log is often the host killing the process because the memory limit sits too close to your heap setting. Paper suggests keeping the heap 1 to 2 GB below the container limit. How to set it is in my RAM guide.
When the CPU is the real limit
The main tick loop runs on a single thread, so past a point more cores won't help. What helps is a CPU with strong single-thread performance, with at least 4 threads available to the server. Low total CPU% on a many-core machine can be perfectly normal. If TPS is still bad after everything above and the profile doesn't point at any one plugin, farm or setting, the machine is probably the limit. Compare what spark says to the plan you're paying for, and see what that costs in my server cost breakdown. A faster CPU, not just more cores or RAM, is the fix at that point, not another config tweak.
The checklist
- Run
/spark tps. Server lag, network or client? - Lower view and simulation distance a step at a time.
- Run Paper.
- Pre-generate and set a border.
- Profile with spark during the lag.
- Fix the farm, redstone or plugin it points to.
- Check memory and GC, then CPU.
Re-check TPS after every change. Boring, but it's how you actually learn what worked.