Minecraft Server: Lag and Performance — Fix
The Problem
Your Minecraft server is lagging — players experience rubber-banding, delayed block breaking, slow inventory updates, or choppy entity movement. The server TPS (ticks per second) drops below the ideal 20 TPS, and the console may show “Can’t keep up! Is the server overloaded?” warnings.
Updated March 2026: Verified with latest Docker images and configurations.
Quick Diagnosis
Check your server’s TPS first. This tells you whether the issue is server-side or client-side:
In-game (with operator permissions):
/debug start
# Wait 10 seconds
/debug stop
With Paper/Spigot:
/tps
| TPS | Status | Cause |
|---|---|---|
| 20.0 | Perfect | No server-side lag |
| 18-19.9 | Good | Minor fluctuations, acceptable |
| 15-17.9 | Noticeable | Players feel slight delay |
| 10-14.9 | Bad | Significant rubber-banding |
| <10 | Unplayable | Server is overloaded |
If TPS is 20 but players report lag: The issue is network latency (client-server ping), not server performance. Check player ping with /ping <player> on Paper servers.
The Fix
Method 1: JVM Memory and Garbage Collection
The single biggest performance improvement for most servers is proper JVM tuning. Default Java settings waste memory and cause GC (garbage collection) pauses that freeze the server for 50-200ms.
Recommended JVM flags for Paper/Spigot (Aikar’s flags):
java -Xms6G -Xmx6G \
-XX:+UseG1GC \
-XX:+ParallelRefProcEnabled \
-XX:MaxGCPauseMillis=200 \
-XX:+UnlockExperimentalVMOptions \
-XX:+DisableExplicitGC \
-XX:+AlwaysPreTouch \
-XX:G1NewSizePercent=30 \
-XX:G1MaxNewSizePercent=40 \
-XX:G1HeapRegionSize=8M \
-XX:G1ReservePercent=20 \
-XX:G1HeapWastePercent=5 \
-XX:G1MixedGCCountTarget=4 \
-XX:InitiatingHeapOccupancyPercent=15 \
-XX:G1MixedGCLiveThresholdPercent=90 \
-XX:G1RSetUpdatingPauseTimePercent=5 \
-XX:SurvivorRatio=32 \
-XX:+PerfDisableSharedMem \
-XX:MaxTenuringThreshold=1 \
-jar server.jar --nogui
Key rules:
-Xmsand-Xmxmust be equal — prevents the JVM from constantly resizing the heap- Don’t allocate more than 10-12 GB — larger heaps cause longer GC pauses
- Don’t allocate less than 4 GB for 10+ players
For Docker Compose, set in environment:
services:
minecraft:
image: itzg/minecraft-server:java21
environment:
MEMORY: "6G"
JVM_XX_OPTS: "-XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1"
Method 2: Use Paper Instead of Vanilla
Paper (fork of Spigot, which is a fork of CraftBukkit) includes hundreds of performance optimizations that the vanilla server lacks. Switching from Vanilla to Paper typically doubles your TPS capacity with the same hardware.
Switch in Docker:
services:
minecraft:
image: itzg/minecraft-server:java21
environment:
TYPE: PAPER
VERSION: "1.21.4"
Paper’s key optimizations:
- Async chunk loading (vanilla loads chunks on the main thread)
- Entity activation ranges (entities far from players tick less frequently)
- Optimized redstone processing
- Reduced hopper lag
- Better mob spawning algorithms
Method 3: Reduce View Distance and Simulation Distance
View distance controls how many chunks are loaded. Each additional chunk loaded costs CPU and RAM. The default (10 chunks) is overkill for most servers.
In server.properties:
view-distance=8 # Default 10 — reduce to 6-8
simulation-distance=6 # Default 10 — reduce to 4-6
Impact:
| View Distance | Chunks Loaded (per player) | RAM per Player |
|---|---|---|
| 10 (default) | 441 | ~200 MB |
| 8 | 289 | ~130 MB |
| 6 | 169 | ~75 MB |
| 4 | 81 | ~35 MB |
Reducing view distance from 10 to 6 cuts chunk processing by 62%. Players rarely notice the difference — client-side rendering fills in the gap.
Method 4: Optimize Paper/Spigot Configuration
spigot.yml — entity activation ranges:
world-settings:
default:
entity-activation-range:
animals: 16 # Default 32
monsters: 24 # Default 32
raiders: 48 # Default 48
misc: 8 # Default 16
water: 8 # Default 16
villagers: 16 # Default 32
paper-world-defaults.yml — reduce entity processing:
entities:
spawning:
per-player-mob-spawns: true # Default true (Paper)
mob-spawner-tick-rate: 2 # Default 1 — doubles spawner efficiency
behavior:
disable-chest-cat-detection: true # Saves entity scanning
bukkit.yml — reduce mob counts:
spawn-limits:
monsters: 50 # Default 70
animals: 8 # Default 10
water-animals: 3 # Default 5
ambient: 1 # Default 15
Method 5: Pre-Generate Chunks
Chunk generation is the most CPU-intensive operation. Pre-generating the world eliminates lag spikes when players explore new areas.
With Chunky plugin (Paper/Spigot):
/chunky radius 5000
/chunky start
This generates all chunks within 5,000 blocks of spawn. Let it run overnight — generation speed varies but typically processes 100-500 chunks per second.
Method 6: Hardware Optimization
Minecraft servers are single-threaded for the main game loop. Clock speed matters more than core count.
| Bottleneck | Solution |
|---|---|
| CPU (most common) | Higher clock speed CPU. Intel i5/i7 or AMD Ryzen 5/7. |
| RAM | 4 GB minimum, 6-8 GB recommended for 10-20 players |
| Disk I/O | SSD required. HDD causes chunk load lag. NVMe ideal. |
| Network | 100 Mbps sufficient. Latency matters more than bandwidth. |
VPS recommendations for Minecraft:
| Players | CPU | RAM | Cost |
|---|---|---|---|
| 1-5 | 2 vCPU | 4 GB | $10-15/month |
| 5-15 | 4 vCPU | 8 GB | $20-30/month |
| 15-30 | 4-6 vCPU | 12-16 GB | $30-50/month |
| 30+ | Dedicated server | 32+ GB | $50-100/month |
Prevention
- Use Paper — not Vanilla. The performance difference is dramatic.
- Set Aikar’s JVM flags from day one — not after lag appears
- Pre-generate your world before inviting players
- Monitor TPS — install a monitoring plugin and alert on TPS < 18
- Limit entity farms — mob farms and hopper chains are the #1 cause of lag on established servers. Use
entity-activation-rangesettings aggressively. - Set a world border — prevents infinite world growth. Use
/worldborder set 10000for a reasonable play area. - Regular restarts — schedule daily restarts to clear memory leaks. Most Docker setups can use a cron job to
docker compose restart minecraftat 4 AM.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments