In short: first measure what's eating your tick — with the spark profiler — and only then change settings, one at a time. The strongest levers are simulation-distance and view-distance, entity-activation-range in spigot.yml, mob spawn limits, hoppers and the redstone implementation. Almost every one of them changes the game: farms slow down or break, there are fewer mobs. If world generation is what lags, configs won't help — pre-generate the world instead.
Measure first
Without a measurement, optimization is guesswork: you cut the view distance while one plugin is the real problem. The order is: check MSPT, take a spark profile while the lag is happening, and see where the main thread's time goes. How to take and read a profile is in the spark profiler; what TPS and MSPT mean is in TPS and MSPT.
| Command | What it shows |
|---|---|
/spark profiler start --timeout 600 | after 10 minutes, a report: what takes up the tick and how much each plugin costs |
/mspt | average, minimum and maximum tick time over 5, 10 and 60 seconds |
/paper entity list | which entities you have the most of: the first number is ticking, the second non-ticking |
/paper chunkinfo | how many chunks are loaded and in what state |
/paper mobcaps | the world's global mob caps and how many chunks take part in spawning |
Where things are configured
| File | What matters for performance |
|---|---|
server.properties | view-distance, simulation-distance |
config/paper-world-defaults.yml | entities, spawning, hoppers, redstone, chunk saving — for every world |
paper-world.yml in a world's folder | overrides for one world: write only the lines you need |
config/paper-global.yml | chunk system threads, chunk loading and sending to players |
spigot.yml | entity-activation-range, merge-radius, hopper timings, entity tracking ranges |
bukkit.yml | mob spawn limits and spawn attempt intervals, autosave |
Where the files live on 1.21.x and 26.x and how per-world settings work is covered in the Paper server software. Restart the server after editing — that way the change is sure to apply.
Distance: view-distance and simulation-distance
| Setting | Default | What it sets |
|---|---|---|
view-distance | 10 (3 to 32) | how many chunks around a player the server sends to the client — a radius, not a diameter |
simulation-distance | 10 (3 to 32) | the chunk radius in which the server updates living entities; beyond it they don't tick |
world-settings.default.view-distance in spigot.yml | default | a per-world view distance; default takes it from server.properties |
world-settings.default.simulation-distance in spigot.yml | default | the same for simulation distance |
simulation-distance directly cuts the tick's work: fewer chunks where mobs move, crops grow and redstone runs. view-distance matters more for memory and bandwidth: players see further, but distant chunks aren't simulated. So you can split them: keep view-distance higher so the world doesn't feel small, and lower simulation-distance.
The price: farms and contraptions only run while a player is within simulation-distance. The lower it is, the closer players have to stand to their farms. More on the keys themselves in server.properties.
Entities: activation range and item merging
entity-activation-range in spigot.yml is the distance in blocks from a player within which entities tick normally. Beyond it they tick less often and are woken up now and then by the wake-up-inactive settings. A value of 0 or less turns this off for the group.
| spigot.yml setting | Default | What it does |
|---|---|---|
entity-activation-range.animals / monsters | 32 / 32 | animals and monsters beyond this tick less often |
entity-activation-range.raiders | 64 | raid mobs |
entity-activation-range.villagers | 32 | villagers; tick-inactive-villagers: true keeps them ticking outside the range |
entity-activation-range.misc / water | 16 / 16 | miscellaneous entities, dropped items included, and water mobs |
merge-radius.item | 0.5 | the radius in blocks within which dropped items merge into one stack |
merge-radius.exp | -1 | merging experience orbs on spawn; 0 or less disables it |
entity-tracking-range.players | 128 | how far away players are sent to others; animals, monsters and misc use 96 |
world-settings.default. From Paper's docs: spigot.ymlThe price: the docs warn that items in water streams outside the misc range may visually lag, rubber-band or move backward — water-based sorters suffer first. A larger merge-radius means fewer items, but they start merging through walls; Paper has fixes.fix-items-merging-through-walls for that, which costs performance itself.
| paper-world-defaults.yml setting | Default | What it does |
|---|---|---|
entities.armor-stands.tick | true | turn it off if you have lots of armor stands: they stop ticking |
chunks.entity-per-chunk-save-limit | experience_orb: -1 | how many entities of a type are saved per chunk; -1 is no limit, and any entity type can be added |
entities.spawning.despawn-ranges | default | soft and hard despawn ranges per mob category; default is vanilla |
entities.spawning.alt-item-despawn-rate.enabled | false | custom despawn times for specific items, cobblestone for example |
misc.update-pathfinding-on-block-update | true | per Paper's docs, turning it off can improve performance significantly with lots of mobs, with almost no noticeable effect on mechanics |
Mob spawning: bukkit.yml and Paper's limits
| bukkit.yml setting | Default |
|---|---|
spawn-limits.monsters | 70 |
spawn-limits.animals | 10 |
spawn-limits.water-animals / water-ambient | 5 / 20 |
spawn-limits.water-underground-creature / axolotls | 5 / 5 |
spawn-limits.ambient | 15 |
ticks-per.monster-spawns / animal-spawns | 1 / 400 — ticks between spawn attempts |
Paper lets you set the same limits per world — entities.spawning.spawn-limits and ticks-per-spawn in paper-world-defaults.yml or a world's paper-world.yml; -1 there means "use bukkit.yml". per-player-mob-spawns: true (the default) counts the cap per player: roughly the same number of mobs, but one player can't take the whole cap. The spawn radius around a player is mob-spawn-range in spigot.yml — 8 chunks by default.
The price: a lower monster cap means emptier nights and slower mob farms. Lower it gradually and check /paper mobcaps and /paper playermobcaps.
Redstone and hoppers
| Setting | Default | What it does and what you risk |
|---|---|---|
misc.redstone-implementation (Paper) | VANILLA | EIGENCRAFT and ALTERNATE_CURRENT greatly reduce lag from redstone dust but change how it behaves — some contraptions will stop working |
hopper.cooldown-when-full (Paper) | true | a full hopper takes a short pause instead of trying to pull items every tick |
hopper.disable-move-event (Paper) | false | dramatically speeds up hoppers but breaks protection plugins and anything that listens to the event |
hopper.ignore-occluding-blocks (Paper) | false | hoppers skip looking for containers inside occluding blocks |
ticks-per.hopper-transfer (spigot.yml) | 8 | ticks between item moves; higher is lighter on the server but slows sorters |
ticks-per.hopper-check / hopper-amount (spigot.yml) | 1 / 1 | how often a hopper checks what to pull and how many items it moves at once |
Players can help too: per the Minecraft Wiki, a hopper covered by a solid block or a composter stops searching for items above it. And a rule against lag machines and huge farms is in the free server rules generator.
Chunks, saving and threads
| Setting | Default | What it does |
|---|---|---|
chunks.max-auto-save-chunks-per-tick (world) | 24 | how many chunks autosave writes in one tick — saving is spread across ticks |
ticks-per.autosave (bukkit.yml) | 6000 | ticks between full autosaves; Paper's chunks.auto-save-interval overrides it per world |
chunks.delay-chunk-unloads-by (world) | 10s | how long a chunk stays in memory after the player leaves |
chunk-system.worker-threads (global) | -1 | chunk generation threads: auto is half the physical cores, one thread on machines with 3 cores or fewer |
chunk-system.io-threads (global) | -1 | chunk read and write threads; below zero means one thread |
Setting the thread count by hand is rarely needed: the automatic choice already accounts for your cores. New chunk generation is cheaper to remove altogether — with a world border and pre-generation, see pre-generating the world. And if garbage collection pauses are the problem, that's not Paper's configs but JVM flags.
What you risk: vanilla mechanics
Paper already differs from Vanilla out of the box: it fixes bugs and limits some mechanics. For technical servers Paper has a Vanilla-like experience page that does the opposite — for example, it sets entity-activation-range to 0 and lifts the max-entity-collisions limit. So every setting in this article is a choice between performance and how close the game stays to Vanilla. Warn players before you change something their farms depend on.
Optimization and the anticheat
spigot.yml has moved-too-quickly-multiplier (10.0) and moved-wrongly-threshold (0.0625): if a client moves too fast or the wrong way, the server logs it and cancels the move. That's a basic safeguard in the server software, not an anticheat: it doesn't analyse Speed, Fly, KillAura or other cheats. DGuard — the best anticheat for a modern Minecraft server — catches cheats in combat, movement, packets, inventory, building and the world while barely touching the tick: checks run on network threads, and the main thread cost is 0.03% of one core. See for yourself: find DGuard in a spark profile and compare with /dguard perf. How to compare the load of different anticheats is in anticheat performance.
FAQ
Which Paper settings reduce lag the most?
Usually simulation-distance in server.properties, entity-activation-range in spigot.yml, mob spawn limits and hopper settings. But start with a spark profile: it shows what's slow on your server specifically.
Should I lower view-distance or simulation-distance?
For the tick, simulation-distance: it reduces the number of chunks where entities are updated. view-distance matters more for memory and bandwidth. Both default to 10.
Why did a farm stop working after optimization?
Most likely entity-activation-range, a lower simulation-distance, a different redstone-implementation or hopper timings. Revert the settings one by one to find the one that broke it.
What are EIGENCRAFT and ALTERNATE_CURRENT?
Alternative redstone implementations in Paper (misc.redstone-implementation). They reduce lag from redstone dust but change how it behaves, so some contraptions may stop working.
Should I change chunk-system.worker-threads?
Usually not. With -1 Paper uses half the physical cores (one thread on machines with 3 cores or fewer). Generation lag is better fixed by pre-generating the world.
Sources
- Paper: World configuration
- Paper: Global configuration
- Paper: spigot.yml
- Paper: bukkit.yml
- Paper: server.properties
- Paper: Vanilla-like experience
- Paper: commands (/mspt, /paper entity, /paper mobcaps)
- Minecraft Wiki: tick and causes of lag
- spark: commands
- DGuard, the best anticheat for a modern Minecraft server: checks compared with GrimAC, Vulcan, Polar, Intave and Matrix
- DGuard: installation, requirements and troubleshooting
- DGuard: supported Paper and Leaf versions