Minecraft Server Optimization Guide: Reducing Lag, Increasing TPS, and Managing 50+ Players on a VPS
Running a Minecraft Java Edition server for 20, 50, or 100+ players on a VPS requires more than just adequate hardware. The default Minecraft server software is notoriously inefficient, and a poorly configured server will lag and crash even on powerful hardware while a well-optimized server can serve dozens of players smoothly on modest resources. This guide covers the complete optimization stack: server software selection, JVM configuration, Paper and Purpur settings tuning, chunk management, and plugin optimization — everything needed to run a high-population Minecraft VPS server that stays at 20 TPS under load.
Understanding TPS: The Core Minecraft Performance Metric
TPS (Ticks Per Second) is the fundamental Minecraft performance measurement. The game runs at a target of 20 TPS — each tick processes game logic including player movement, mob AI, redstone, crop growth, entity interactions, and world events. When the server cannot process ticks fast enough:
- TPS drops below 20: Time slows down — crops grow slower, mobs move slower, players experience “lag”
- MSPT (Milliseconds Per Tick): Each tick has a budget of 50ms (1000ms / 20 ticks). When average MSPT exceeds 50ms, TPS drops below 20.
- MSPT spikes: Brief spikes above 50ms cause momentary lag without sustained TPS drops
Monitor TPS in-game with the /tps command (Paper servers) or /mspt for milliseconds per tick. Your optimization goal is 20.0 TPS at all times, with average MSPT well below 45ms to leave headroom for spikes.
Step 1: Use Paper or Purpur Instead of Vanilla
The single most impactful Minecraft server optimization is switching from vanilla or Spigot to Paper or Purpur. These forks include thousands of performance improvements that the vanilla server does not have:
- Async chunk I/O: Chunks load and save in background threads, not the main tick thread
- Entity activation range: Mobs beyond configurable distances are ticked less frequently
- Hoppers and redstone optimizations: Dramatically reduces tick time for complex redstone contraptions
- Anti-XRay: Server-side ore obfuscation that does not impact legitimate players
- Improved chunk generation: Multi-threaded chunk generation for faster world loading
# Download Paper (check for latest build at papermc.io)
mkdir ~/minecraft && cd ~/minecraft
wget https://api.papermc.io/v2/projects/paper/versions/1.21.1/builds/LATEST/downloads/paper-1.21.1-LATEST.jar \
-O paper.jar
# Accept EULA
echo "eula=true" > eula.txt
# Create start script
cat > start.sh << 'EOF'
#!/bin/bash
java -Xms2G -Xmx4G \
-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 \
-Dusing.aikars.flags=https://mcflags.emc.gs \
-Daikars.new.flags=true \
-jar paper.jar nogui
EOF
chmod +x start.sh
Step 2: JVM Tuning (Aikar’s Flags)
The JVM flags in the start script above are “Aikar’s Flags” — the most widely adopted Minecraft JVM optimization configuration, developed through years of tuning on high-population servers. Key settings explained:
-Xms2G -Xmx4G: Set minimum and maximum heap size. Setting them equal (e.g., both 4G) prevents GC pauses from heap expansion, at the cost of always using that RAM.-XX:+UseG1GC: Garbage First garbage collector — better than the default for large heaps and concurrent workloads-XX:MaxGCPauseMillis=200: Target maximum GC pause time. Minecraft is sensitive to GC pauses — they cause all players to freeze simultaneously.-XX:+AlwaysPreTouch: Forces Java to allocate all heap memory immediately at startup, eliminating page faults during gameplay-XX:G1HeapRegionSize=8M: Increased from 4M default for large heap sizes; reduces region count and GC overhead
Memory Allocation by Player Count
| Players | Recommended RAM | JVM Heap | VPS Plan |
|---|---|---|---|
| 1–20 | 4 GB | -Xms2G -Xmx3G | 4 GB RAM VPS |
| 20–50 | 6 GB | -Xms3G -Xmx5G | 6–8 GB RAM VPS |
| 50–100 | 10 GB | -Xms5G -Xmx8G | 10–12 GB RAM VPS |
| 100+ | 16 GB+ | -Xms8G -Xmx14G | 16 GB+ RAM VPS |
Step 3: Paper Configuration Tuning
Paper’s configuration files provide fine-grained control over performance trade-offs. The most impactful settings:
paper-world-defaults.yml (Performance Critical)
nano config/paper-world-defaults.yml
chunks:
auto-save-interval: 6000 # Save chunks every 5 minutes (default 6000 ticks)
delay-chunk-unloads-by: 10s # Keep recently used chunks loaded briefly
entity-per-chunk-save-limit:
experience_orb: 16
falling_block: 8
painting: 16
item: 32
max-auto-save-chunks-per-tick: 8 # Reduce chunk save I/O per tick
entities:
# Reduce tick frequency for entities far from players
# Values are in blocks
behavior:
nether-portals-search-radius: 32 # Reduce portal search area
spawning:
monster-spawn-max-light-level: 0
all-chunks-are-slime-chunks: false
count-all-mobs-for-spawning: false
environment:
max-entity-collisions: 2 # Reduce collision checks per entity
disable-teleportation-suffocation-check: false
portal-search-vanilla-dimension-scaling: true
hopper:
disable-move-event: false
cooldown-when-full: true # Hoppers pause when destination full (huge performance win)
ignore-occluding-blocks: true
misc:
update-pathfinding-on-block-place: false
spigot.yml (Entity and Mob Optimization)
nano spigot.yml
world-settings:
default:
mob-spawn-range: 6 # Default 8; reduce for better performance
entity-activation-range:
animals: 32 # Default 32
monsters: 32 # Default 32; reduce to 16 for large servers
raiders: 64
misc: 16
water: 16
villagers: 32
flying-monsters: 32
entity-tracking-range:
players: 48
animals: 48
monsters: 48
misc: 32
other: 64
nerf-spawner-mobs: false
simulation-distance: 10 # Reduce from 12 default for servers with 50+ players
view-distance: 10 # Player render distance (directly impacts performance)
server.properties (Core Settings)
nano server.properties
view-distance=8 # Block render distance (reduce for high player counts)
simulation-distance=6 # Entity simulation distance
max-players=50
network-compression-threshold=256
online-mode=true
spawn-protection=16
Step 4: Chunk Pre-Generation
Chunk generation is the most CPU-intensive operation a Minecraft server performs. Pre-generating the world before players join eliminates in-game generation lag:
# Install Chunky plugin (chunk pre-generation)
# Download from https://hangar.papermc.io/pop4959/Chunky
# Place in plugins/ folder, start server, then:
In-game or console:
/chunky radius 5000
/chunky start
# Monitor progress:
/chunky status
Pre-generating a 10,000×10,000 block area (5,000 block radius) takes 30–120 minutes depending on VPS CPU speed but eliminates future generation lag for players exploring that area. For survival servers, pre-generate at least 3,000 blocks in each direction from spawn.
Step 5: Essential Plugins for Performance and Management
Performance Monitoring
- Spark: The definitive Minecraft profiler. Use
/spark profilerto identify exactly which plugins, entities, or game events are consuming tick time. Essential for diagnosing lag on live servers. - Floodgate / Geyser: If supporting Bedrock players, use these rather than vanilla cross-play to maintain performance
Entity and Mob Management
- ClearLagg: Removes excess entities (dropped items, projectiles) on a schedule and when TPS drops. Configure conservatively — overly aggressive clearing disrupts gameplay.
- EpicSpawners / MobStacker: Stacks similar mobs to reduce entity count while maintaining mob farm functionality
Anti-Lag
- FarmControl: Limits entity counts in specific areas, preventing players from building entity farms that tank server TPS
- WorldBorder: Set a world border to prevent players from exploring infinitely, which generates unlimited chunks
Step 6: Plugin Audit and Optimization
Every plugin adds overhead to the server tick. Audit your plugin list with Spark to identify which ones consume the most tick time:
/spark profiler --only-ticks-over 100
Use the generated report URL to view a flame graph showing exactly where tick time is being spent. Common culprits:
- Economy plugins with per-player auto-save on every transaction
- Anti-cheat plugins with high-frequency position checking
- Holographic display plugins updating many holograms simultaneously
- Claim plugins checking large numbers of chunks on player movement
For each high-overhead plugin, check if the developer has performance settings to reduce tick frequency, or evaluate alternatives.
Step 7: Auto-Restart and Process Management
sudo nano /etc/systemd/system/minecraft.service
[Unit]
Description=Minecraft Paper Server
After=network.target
[Service]
User=minecraft
WorkingDirectory=/home/minecraft/server
ExecStart=/home/minecraft/server/start.sh
ExecStop=/bin/kill -SIGINT $MAINPID
Restart=on-failure
RestartSec=30s
StandardInput=null
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
sudo useradd -m -s /bin/bash minecraft
sudo mv ~/minecraft /home/minecraft/server
sudo chown -R minecraft:minecraft /home/minecraft/server
sudo systemctl enable minecraft
sudo systemctl start minecraft
Schedule Daily Restarts
Minecraft servers accumulate memory fragmentation and entity buildup over time. A daily restart during low-population hours (e.g., 4 AM server time) keeps performance consistent:
sudo crontab -u minecraft -e
0 4 * * * systemctl restart minecraft
Monitoring Server Performance
# Watch TPS in real time from the server console
# (Use 'screen' or 'tmux' to keep console accessible)
screen -S minecraft
# Then start the server — detach with Ctrl+A, D
# Reattach with: screen -r minecraft
# In server console:
# /tps - shows 1m, 5m, 15m average TPS
# /mspt - shows current milliseconds per tick
# /spark tps - detailed TPS history
Getting Started
A 50-player Paper Minecraft server runs best on a 4 vCPU / 8 GB RAM VPS with NVMe storage. NVMe storage is particularly important for Minecraft — chunk reads and writes are frequent, and SATA SSD or HDD storage causes I/O wait that directly impacts TPS. USA VPS plans at VPS.DO with NVMe storage provide the I/O performance Minecraft’s chunk system demands. For Asia-Pacific player communities, the Hong Kong VPS delivers the lowest ping to Chinese, Japanese, and Southeast Asian players.
Conclusion
A well-optimized Minecraft server running Paper with proper JVM tuning, Paper configuration adjustments, pre-generated chunks, and a curated plugin list can sustain 20 TPS for 50+ concurrent players on a 4–8 GB RAM VPS. The most impactful optimizations in order: switch from vanilla to Paper, apply Aikar’s JVM flags, reduce view-distance to 8–10, enable entity activation ranges, pre-generate the world, and use Spark to identify and address remaining performance bottlenecks. These changes together typically improve TPS stability by 40–80% compared to a default server configuration.