How to Optimize Your Minecraft Server to Fix Lag & Improve TPS
A complete guide to all the methods you can use to improve the user experience on your Minecraft server.
Your Minecraft server runs on a simple clock. Twenty ticks per second. Every tick processes mob AI, block updates, redstone signals, player movement, and about a thousand other calculations. When those calculations take longer than 50 milliseconds, ticks start backing up. Players notice blocks reappearing after they break them. Mobs teleport instead of walking. The server feels sluggish even though everyone’s ping looks fine.
This is server lag, and throwing more RAM at it usually doesn’t help.
Minecraft server optimization comes down to three things: picking the right server software, tuning your configuration files, and adding optimization mods if you’re running Fabric or Forge.
This guide covers the practical fixes. We’ll skip the hardware recommendations since that’s a separate topic entirely. Instead, we’re focusing on what you can actually change today to reduce lag on your Minecraft server without spending money on upgrades.
Understanding TPS and Server Lag
TPS stands for ticks per second. Minecraft targets 20 TPS. Hit that target consistently and gameplay feels smooth. Miss it and everything slows down proportionally.
Here’s what different TPS ranges actually feel like:
- 20 TPS – Perfect. The server handles everything within budget. No lag.
- 18-19 TPS – Minor slowdown. Most players won’t notice unless they’re paying attention.
- 15-18 TPS – Noticeable problems. Blocks reappear after mining. Mob movement looks choppy. Redstone timing gets unreliable.
- 10-15 TPS – Significant lag. Rubber-banding becomes common. Combat feels unresponsive.
- Below 10 TPS – Nearly unplayable. The server is drowning.

You can check your TPS with /tps on Paper/Spigot servers or by installing the Spark profiler. But TPS alone doesn’t tell the whole story. MSPT (milliseconds per tick) shows how long each tick actually takes to process. A server might show 20 TPS while averaging 45ms per tick, meaning it’s running right at the edge of falling behind.
Server Lag vs. Client Lag vs. Network Lag
These get confused constantly, but they’re different problems with different solutions.
Server lag affects everyone equally. TPS drops, the whole world slows down. Fixing this requires server-side optimization.
Client lag is a player’s computer struggling to render the game. Their FPS tanks but the server runs fine. Nothing you can do about this from the server side except reduce entity counts and particle effects.
Network lag shows up as high ping for specific players. They rubber-band while others play normally. Usually, a routing issue between the player and your server location. Optimization won’t fix geography.
When players complain about lag, figure out which type you’re dealing with first. Run /tps or check Spark. If TPS is solid at 19-20, the problem isn’t your server.
Choosing the Right Server Software
The server JAR you run matters more than most people realize. Vanilla Minecraft server software wasn’t built for multiplayer performance. It works fine for a few friends, but start adding players and plugins and you’ll hit walls fast.
Vanilla, CraftBukkit, and Spigot
These are outdated choices for anyone serious about performance. Vanilla offers zero optimization options. CraftBukkit added plugin support, but not much else. Spigot improved on CraftBukkit with some basic performance tweaks back in 2012, but it leaves a lot of performance on the table compared to modern alternatives.
Spigot still works. Plenty of servers run it. But benchmarks consistently show it struggling to maintain 20 TPS under loads that Paper handles easily. One test with 50 simulated players had Spigot averaging around 18.5 TPS while Paper held steady at 19.8.
Paper
Paper is the current standard for plugin-based servers. It’s a Spigot fork with aggressive optimizations baked in: async chunk loading, improved entity tracking, faster lighting calculations, and dozens of configuration options Spigot doesn’t expose.
Performance gains typically run 10-20% better than Spigot depending on your setup. Paper also fixes vanilla bugs that Mojang hasn’t addressed and patches exploits that could crash your server. All Spigot and Bukkit plugins work on Paper without modification.
If you’re running survival, SMP, factions, skyblock, or pretty much any plugin-based server, Paper should be your starting point. Most Minecraft server hosts offer it as a one-click install option.
Pufferfish
Pufferfish takes Paper and pushes optimization further. The headline feature is DAB (Dynamic Activation of Brain), which reduces how often distant mob AI ticks. Instead of every mob running full AI calculations every tick, mobs further from players think less frequently.
Pufferfish also includes faster hopper logic, optimized entity tracking, SIMD-accelerated map rendering, and memory tweaks that reduce garbage collection pauses. For servers with 50+ players or heavy entity loads, Pufferfish can squeeze out a few extra TPS when Paper hits its limits.
Purpur
Purpur builds on Pufferfish but focuses on customization rather than raw performance. It includes everything from Pufferfish plus hundreds of gameplay toggles: rideable mobs, configurable block behaviors, alternate mechanics.
The performance is identical to Pufferfish since it inherits all those optimizations. You’d pick Purpur over Pufferfish if you want granular control over gameplay mechanics. All the extra features are disabled by default, so it behaves like Pufferfish out of the box.
Folia
Folia is Paper’s experimental multi-threaded fork. It divides your world into independent regions that tick on separate CPU threads. In theory, this means different areas of your map can process simultaneously instead of waiting in line.
The catch: plugins must be written specifically for Folia. Most existing plugins won’t work. And the performance benefits only show up when players are spread across the map. If everyone clusters at spawn, you’re back to single-threaded performance.
Folia makes sense for massive servers with 100+ concurrent players spread across a large world. For everyone else, stick with Paper or Pufferfish.
Fabric and Forge for Modded Servers
Modded servers work differently. Fabric is a lightweight mod loader that starts close to vanilla performance. You add optimization through server-side mods like Lithium, Starlight, and Krypton. This modular approach lets you pick exactly which optimizations you want.
Forge handles heavier modpacks but tends to be more resource-intensive. Performance depends heavily on which mods you’re running. The optimization strategy shifts to adding performance mods (Canary, AI Improvements, etc.) alongside your gameplay mods.
Check our Minecraft server optimization mods list for the full breakdown of which mods to install on each platform.
Quick Recommendations
| Server Type | Recommended Software |
|---|---|
| Vanilla/Survival/SMP | Paper |
| High player count (50+) | Pufferfish |
| Custom mechanics needed | Purpur |
| 100+ players spread out | Folia (if plugins support it) |
| Light modpacks | Fabric + optimization mods |
| Heavy modpacks | Forge + optimization mods |
Essential Configuration Tweaks
Switching to Paper or Pufferfish gets you halfway there. The other half is tuning the configuration files these server JARs expose. Default settings prioritize vanilla behavior over performance, which means you’re leaving TPS on the table until you adjust them.
There’s no universal “best” config. Optimal settings depend on your player count, world size, and what kind of gameplay you’re running. But the recommendations below work well for most survival and SMP servers. Start here and adjust based on what Spark tells you.

server.properties
Two settings matter most here: simulation-distance and view-distance. These control how much of the world stays active around each player.
simulation-distance determines how far from players the server actually ticks entities, redstone, and block updates. Default is 10 chunks, which creates a 21×21 chunk area per player. That’s a lot of mobs running AI calculations.
Set this to 4-5 for most servers. Going lower than 4 can break mob farms and redstone contraptions that expect vanilla behavior.
view-distance controls how far players can see. Chunks beyond simulation distance still render on the client, they just don’t tick. You can keep this higher than simulation distance (7-10) to give players a decent horizon without the server processing all those chunks.
This separation is the single biggest Minecraft server optimization you can make through config alone. Players see far, but only nearby chunks cost CPU cycles.
simulation-distance=4
view-distance=8bukkit.yml
Bukkit controls mob spawn limits and frequencies. The defaults assume single-player conditions where having lots of mobs makes the world feel alive. On a multiplayer server with 20 people exploring different areas, those numbers add up fast.
spawn-limits caps how many mobs can exist per world. Lower these to reduce entity counts:
spawn-limits:
monsters: 50
animals: 8
water-animals: 3
water-ambient: 5
ambient: 1 ticks-per controls how often the server attempts mob spawns. Higher numbers mean less frequent spawn attempts, spreading the CPU load:
ticks-per:
monster-spawns: 10
animal-spawns: 400
water-spawns: 20
ambient-spawns: 20 Monsters spawning every 10 ticks instead of every tick means spawn calculations happen twice per second instead of twenty times. Players won’t notice the difference, but your TPS will.
spigot.yml
Spigot’s config offers more granular control over entity behavior. These settings have a big impact on how to reduce Minecraft server lag from mob AI and item clutter.
entity-activation-range puts distant entities to sleep. Mobs outside these ranges stop running AI until a player gets closer:
entity-activation-range:
animals: 16
monsters: 24
raiders: 48
misc: 8
water: 8
villagers: 16
flying-monsters: 32 A cow 20 blocks away doesn’t need to pathfind. It can stand there until someone approaches. These ranges are aggressive but won’t break normal gameplay.
tick-inactive-villagers is critical. Set this to false. Villagers are notoriously expensive because they constantly search for beds, workstations, and gossip partners. Disabling their AI when outside activation range saves significant CPU on any server with trading halls or villages.
tick-inactive-villagers: falsemerge-radius combines nearby items and XP orbs into single entities:
merge-radius:
item: 4.0
exp: 6.0 Instead of 50 separate cobblestone drops from mining, you get a few merged stacks. Instead of 100 XP orbs from a mob grinder, you get larger combined orbs. Fewer entities means less work for the server.
item-despawn-rate controls how long dropped items stick around before vanishing. Default is 6000 ticks (5 minutes). Shortening this cleans up item clutter faster:
item-despawn-rate: 4000 mob-spawn-range should match or stay below your simulation distance. Setting it higher than simulation distance wastes CPU trying to spawn mobs in chunks that aren’t ticking:
mob-spawn-range: 4 max-entity-collisions limits collision calculations per entity. When 100 cows cram into a pen, each one normally checks collisions with all the others. This caps that:
max-entity-collisions: 2 Collision math scales exponentially with entity count. Capping it at 2 prevents crowded farms from tanking your TPS.
paper-world-defaults.yml
Paper exposes the most powerful optimization settings. Some of these deliver massive performance gains with zero noticeable gameplay impact. Check the Paper documentation for the full list, but these are the essentials.
per-player-mob-spawns should be true. Without this, a single player with a good spawn location can consume the entire server’s mob cap, leaving other players in empty worlds:
entities:
spawning:
per-player-mob-spawns: trueredstone-implementation switches to an optimized redstone engine. Set this to ALTERNATE_CURRENT for roughly 10x faster redstone calculations with identical behavior for 99% of contraptions:
redstone-implementation: ALTERNATE_CURRENTThis alone can fix Minecraft server lag on technical servers with lots of redstone.
prevent-moving-into-unloaded-chunks stops players from outrunning chunk loading. When someone flies fast with elytra, this pauses their movement briefly instead of forcing synchronous chunk generation that spikes lag for everyone:
chunks:
prevent-moving-into-unloaded-chunks: truedelay-chunk-unloads-by keeps recently visited chunks in memory for a few seconds. If a player bounces back and forth across a chunk border, the server doesn’t constantly unload and reload:
chunks:
delay-chunk-unloads-by: 10sHopper optimizations address one of the biggest lag sources on survival servers. Hoppers check for items constantly, even when empty or blocked:
hopper:
cooldown-when-full: true
disable-move-event: false
ignore-occluding-blocks: truealt-item-despawn-rate lets common junk despawn faster than valuable items. Cobblestone from a mining session vanishes in 15 seconds while diamonds stick around:
entities:
spawning:
alt-item-despawn-rate:
enabled: true
items:
cobblestone: 300
netherrack: 300
sand: 300
gravel: 300
dirt: 300optimize-explosions uses a faster algorithm for TNT and creeper explosions:
environment:
optimize-explosions: truepurpur.yml
If you’re running Purpur, you get additional options for stubborn performance problems. These go beyond Paper’s settings.
villager.lobotomize completely stops AI for villagers that can’t reach their destination. A villager stuck behind a fence trying to pathfind to an unreachable bed will eventually give up instead of burning CPU forever:
villager:
lobotomize:
enabled: trueuse-alternate-keepalive helps players with unstable connections stay connected instead of timing out:
settings:
use-alternate-keepalive: trueentities-can-use-portals prevents mobs from wandering through Nether portals and loading chunks in other dimensions:
gameplay-mechanics:
entities-can-use-portals: falsevillager search radius limits how far villagers look for beds and workstations. On servers with large villages, this prevents villagers from scanning hundreds of blocks:
villager:
acquisition:
poi-search-radius: 16 Entity Optimization
Entities are the biggest performance drain on most Minecraft servers. Every mob, item drop, minecart, armor stand, and experience orb consumes CPU cycles. A single chunk with 200 cows costs more processing power than 10,000 static blocks.
Each entity runs AI calculations, collision checks, and pathfinding every tick. Twenty ticks per second times 500 entities equals 10,000 entity updates per second. Add players spreading out and loading different chunks, and suddenly your server is tracking thousands of entities simultaneously.
Fixing Minecraft server lag usually starts here.
Villagers Are the Worst
Villagers deserve special attention because they’re disproportionately expensive. Every tick, they check for nearby beds, search for workstations, pathfind to points of interest, gossip with other villagers, track iron golem spawning conditions, and update trade inventories. One villager won’t tank your TPS. Fifty villagers in a trading hall might.
Keep trading halls under 30 villagers and house them in 1×1 cells. A villager in an open space constantly pathfinds to beds and workstations. A villager in a 1×1 space has nowhere to go, so pathfinding returns instantly. Place workstations directly adjacent so they don’t search, and use tick-inactive-villagers: false in spigot.yml.

Mob Farms and Entity Caps
Mob farms are necessary for survival gameplay, but uncontrolled farms that accumulate hundreds of waiting mobs will destroy your TPS. Set expectations with your players upfront. A reasonable target is under 1,000 total entities server-wide and no more than 200 in any single chunk.
The killing mechanism matters more than spawn rates. A farm that spawns 10 mobs per minute but only kills 5 will eventually overflow. Require kill switches on AFK farms so mobs don’t pile up overnight.
Plugins like FarmControl enforce limits automatically. Configure maximum counts per chunk, and the plugin stops breeding or spawning when thresholds are exceeded. Players get notified when they hit limits instead of assuming the server is broken.
Misc Entities Add Up
Armor stands, minecarts, and item frames don’t seem expensive individually. But a decorated base with 100 armor stands holding gear, a rail network with 50 minecarts, and display rooms with 200 item frames creates hundreds of entities that get tracked every tick.
Armor stands are the worst offenders because players use them for custom furniture and statues. A single elaborate build can add hundreds of entities to one chunk. Set lower activation ranges for misc entities in spigot.yml, or use plugins like Insights to set hard limits per region.
Skip the Entity Clearing Plugins
Periodic entity clearing used to be standard practice. Plugins like ClearLagg would announce “clearing items in 60 seconds” and wipe every dropped item on the server.
This is mostly unnecessary now. Proper despawn rates and merge radius settings in spigot.yml handle item cleanup automatically. Paper’s alt-item-despawn-rate clears junk blocks like cobblestone in seconds while leaving diamonds alone. If you’re running ClearLagg to maintain TPS, you’re treating symptoms instead of fixing the actual problem.
Redstone and Hopper Optimization
Redstone and hoppers cause more lag complaints than almost anything else on survival servers. A sorting system that worked fine with 10 players starts stuttering with 30. A mega farm with 200 hoppers runs smooth until someone builds another one nearby.
The problem is how vanilla Minecraft handles these systems. Both redstone dust and hoppers do far more work than necessary, and the inefficiency compounds as builds get larger.
Why Hoppers Are So Expensive
Hoppers check for items constantly. Every hopper on your server looks for items to pull 20 times per second, even when completely empty. It also checks if it can push items into the container below, even when that container is full.
A small sorting system with 20 hoppers runs 400 item checks per second before a single item enters the system. A large storage room with 200 hoppers runs 4,000 checks per second. Multiply that across several player bases and you’re burning CPU cycles on millions of checks that do nothing.
The config tweaks from Section 3 help significantly. Setting hopper.cooldown-when-full: true stops hoppers from checking when their destination is full. Increasing hopper-transfer and hopper-check intervals in spigot.yml reduces how often these checks happen.
But design matters too. Encourage players to use water streams for item transport instead of hopper chains. A line of 20 hoppers moving items horizontally costs 20x more than a water stream feeding a single hopper. Droppers activated by redstone clocks are another alternative since they only work when pulsed instead of constantly checking.
Redstone Lag
Vanilla redstone is notoriously inefficient. When redstone dust updates, it recalculates signal strength for itself and all adjacent dust, even when nothing actually changed. Complex circuits trigger cascades of redundant updates that waste CPU time.
Paper’s ALTERNATE_CURRENT redstone implementation fixes this. It uses the same algorithm as the Alternate Current mod, eliminating redundant calculations while producing identical outputs. Enabling it is the single biggest redstone optimization available:
redstone-implementation: ALTERNATE_CURRENTThis alone can reduce redstone lag by 90% or more on technical servers.
Build Practices That Help
Some redstone designs are inherently more expensive than others. Players building massive circuits can reduce server impact with a few techniques.
Slower clocks help more than people expect. A 2-tick repeater clock pulses 10 times per second. A 10-second clock pulses once every 10 seconds. If the contraption doesn’t need rapid pulses, slower clocks dramatically reduce update frequency.
Master switches let players disable machines when not in use. A piston door that’s always powered waiting for input costs nothing. A sorting system that runs 24/7 whether items are flowing or not costs plenty. Encourage builds that can be turned off.
When Players Won’t Cooperate
Public servers with technical players will always have redstone-heavy builds. If config changes aren’t enough, plugins like RedstoneLimiter let you cap redstone activity per chunk or disable specific clock speeds.
You can also use WorldGuard to disable redstone entirely in specific regions, or limit which players have permission to place redstone components in certain areas. These are heavy-handed approaches, but sometimes necessary on servers where a few builds cause problems for everyone.
World Pre-generation with Chunky
Chunk generation is one of the most CPU-intensive operations a Minecraft server performs. When a player explores new territory, the server has to generate terrain, place structures, calculate lighting, and populate the area with mobs and features. All of this happens on demand while the server is also processing everything else.
A single player flying with elytra can force the server to generate dozens of chunks per second. Multiple players exploring in different directions can bring even powerful hardware to its knees.
Pre-generating your world eliminates this problem entirely. Generate the chunks before players arrive, and exploration becomes a simple file read instead of complex terrain calculation.
Setting Up Chunky
Chunky is the standard plugin for world pre-generation. It runs asynchronously so your server stays responsive during generation, and it saves progress if you need to stop and resume later.
Before generating, set your world border. There’s no point generating chunks players will never reach, and unlimited generation will eventually fill your storage.
/worldborder center 0 0
/worldborder set 10000This creates a 10,000 block diameter world (5,000 blocks from center in each direction). Adjust based on how much space your players actually need.
Then tell Chunky to generate everything within that border:
/chunky worldborder
/chunky startMonitor progress with /chunky progress. Generation speed depends on your CPU speed and what else the server is doing. A 5,000 block radius takes roughly 2 hours on modern hardware and uses about 2GB of storage.
Don’t Forget Other Dimensions
The Nether and End need pre-generation too. Players exploring Nether highways or hunting End cities cause the same lag spikes as Overworld exploration.
For the Nether, remember that distances are 8x compressed. A 10,000 block Overworld border corresponds to a 1,250 block Nether border:
/chunky world world_nether
/chunky radius 625
/chunky startThe End is trickier since players scatter across islands. Generate a reasonable radius around the main island and accept that outer End exploration will still cause some generation lag.
When to Pre-generate
Run pre-generation before your server goes public, during off-hours, or during scheduled maintenance. Chunky is efficient but still uses significant CPU. Generating while 30 players are online will make their experience worse.

For established servers adding more space, extend your world border gradually and generate in chunks during low-activity periods. Chunky’s pause and resume features make this manageable.
Performance Monitoring Tools
Optimization without measurement is guesswork. You can apply every config tweak in this guide and still have lag if a single plugin or player build is eating 40% of your tick time. Monitoring tools tell you exactly where your server spends its resources so you can fix actual problems instead of imaginary ones.
Spark Profiler
Spark is the standard profiler for Minecraft servers. It works on Paper, Spigot, Fabric, Forge, and pretty much every other server platform. Install it and keep it installed permanently since you never know when you’ll need to diagnose a problem.
The basic commands you’ll use most:
/spark tps shows current TPS, MSPT, and CPU usage. This is your quick health check. If TPS is 20 and MSPT is under 40, your server is healthy. If MSPT regularly exceeds 50, you’re dropping ticks.
/spark profiler starts recording what your server is doing. Let it run for 30-60 seconds during normal gameplay or whenever lag occurs, then stop it with /spark profiler stop. Spark generates a link to a detailed report.
/spark health gives a quick snapshot of server status including memory usage, garbage collection activity, and tick duration breakdown.
/spark heapsummary shows what’s consuming memory. Useful when you suspect a memory leak or want to understand why RAM usage is high.
Reading Spark Reports
Spark reports look intimidating at first. The flame graph shows nested bars representing where CPU time goes. Wider bars mean more time spent. Click any bar to drill down into specifics.

Look for obvious outliers first. If a single plugin or mod takes more than 10-15% of tick time, that’s worth investigating. Entity ticking should ideally stay under 30% of total time. Chunk loading and generation spikes are normal during exploration but shouldn’t dominate during regular play.
Timings Reports
Paper includes a built-in timings system that’s simpler than Spark but still useful for quick diagnostics.
Start with /timings on, wait 5-10 minutes during normal gameplay, then run /timings paste to generate a shareable report. Turn timings off afterward with /timings off since the monitoring itself has a small performance cost.
Conclusion
Most server lag comes from the same handful of sources. Mobs running expensive AI calculations when nobody’s nearby. Hoppers checking for items twenty times per second while empty. Villagers pathfinding to beds they’ll never reach. Redstone doing redundant updates. Players exploring faster than the server can generate chunks.
Paper with proper configs fixes most of it. Set simulation-distance to 4-5, enable ALTERNATE_CURRENT redstone, turn off inactive villager ticking, and pre-generate with Chunky. That handles 80% of performance problems.
For the rest, use Spark. Run a profiler when lag happens. Find out if it’s a plugin, a specific chunk, or a player’s build causing problems. Fix that specific thing instead of applying random optimizations and hoping something works.
Modded servers need Lithium and FerriteCore on Fabric, or Canary and ModernFix on Forge. If your current host can’t keep up even after optimization, check our best Minecraft server picks.
Frequently Asked Questions
Does Paper break vanilla mechanics?
Some. TNT duping doesn’t work. Certain sand duplication glitches are patched. Some quirky redstone behaviors may differ. Technical Minecraft players who rely on specific exploits should check Paper’s documentation or stick with Fabric plus optimization mods.
How often should I restart my server?
Every 24-48 hours. Restarts clear memory fragmentation and reset plugin memory leaks. Modded servers benefit from more frequent restarts since mods tend to leak memory faster.
Can I use multiple optimization mods together?
Yes. Lithium, FerriteCore, and Krypton optimize different systems and don’t conflict. Avoid running mods that do the same thing, like Starlight and ScalableLux together.
Will optimization mods work with modpacks?
Usually. Lithium and FerriteCore ship with many popular modpacks by default. Occasionally a specific mod conflicts, so add one at a time and test.
Why is my TPS low when RAM and CPU usage look fine?
Minecraft is single-threaded. Your CPU might show 25% usage overall, but the one core running the server is maxed. Run /spark profiler to see what’s actually consuming tick time.
Should I use ClearLagg or similar entity clearing plugins?
Probably not. Paper’s built-in despawn rates and merge radius settings handle item cleanup better. If you need constant clearing to maintain TPS, find and fix the source of those entities instead.
Do I need to optimize if I only have a few players?
Less urgently, but yes. Bad settings still waste resources, and proper configs prevent one player’s mega-farm from lagging everyone else.