
Quick Answer: Minecraft 1.21 lag is caused by heavier world generation and more entities. Solve this with: 1) Purpur server jar (best performance fork), 2) Reduce simulation-distance to 4-6, 3) Install Lithium + FerriteCore mods, 4) Use correct JVM flags (Aikar's). A properly configured 4GB VPS will run a 10-15 player server smoothly at 20 TPS.
Why Minecraft 1.21+ Is So Much Heavier
The Technical Changes
Minecraft 1.21 "Tricky Trials" and 1.21+ introduced significant changes:
| Change | Impact on Performance | Percentage of Additional CPU | |-------------|------------------------|------| | Trial Chambers (new structure) | Complex generation with many entities | +15-25% | | Breeze mob | Advanced AI with pathfinding | +10% on spawning | | Wind Charges | Additional projectile physics | +5-10% in combat | | Higher build limit | More chunks to track | +5-15% | | Copper/Tuff variants | More block states in memory | +5% RAM |
Result: A standard 1.20 setup that achieved 20 TPS drops to 15-18 TPS on 1.21 with the same hardware.
The TPS Problem
TPS = Ticks Per Second
Minecraft runs on a "tick loop": the entire world is updated 20 times per second (mob movement, redstone, crop growth, etc.).
- 20 TPS = Perfect, each tick lasts 50ms
- 15-18 TPS = You will notice gameplay lag, movement stuttering
- <15 TPS = Unplayable, severe lag spikes
Step 1: The Right Server Software (Paper vs Purpur vs Forge)
1.1 The Server Software Hierarchy
Vanilla (Mojang) → Bad for performance
↓
Spigot → Basic Optimizations
↓
Paper → Excellent Optimizations + API
↓
Pufferfish → Paper + additional async processing
↓
Purpur → Pufferfish + configuration freedom ⭐ BEST
1.2 Why Purpur?
Purpur = Paper + Pufferfish + extra features
| Feature | Vanilla | Paper | Purpur | |--------|-------------|-------|--------| | Async chunk loading | ❌ | ✅ | ✅ | | Mob AI optimization | ❌ | Basic | Advanced | | Config options | Little | Much | Very much | | Entity activation range | ❌ | Static | Dynamic | | Redstone Optimizations | ❌ | ✅ | ✅+ | | Disable per-mob AI | ❌ | ❌ | ✅ | | Gameplay features | Basic | Basic | Extensive |
Practical example:
On the same 4GB VPS with 10 players:
- Vanilla: 12-15 TPS (unplayable)
- Paper: 18-19 TPS (playable, sometimes lag)
- Purpur: 19.8-20 TPS (perfect)
1.3 Purpur Install
Download:
Go to https://purpurmc.org/downloads
# SSH to your VPS
ssh root@je-vps-ip
# Create server directory
mkdir -p /opt/minecraft-server
cd /opt/minecraft-server
# Download Purpur (replace version with current one)
wget https://api.purpurmc.org/v2/purpur/1.21.1/latest/download -O purpur.jar
# Accept EULA
echo "eula=true" > eula.txt
First start (generates config files):
java -Xms2G -Xmx4G -jar purpur.jar nogui
Stop the server after 30 seconds (Ctrl+C). You now have all the config files.
Step 2: Critical Configuration Adjustments
2.1 server.properties (Basic Settings)
nanoserver.properties
Major changes:
# === PERFORMANCE CRITICAL ===
# Simulation distance: How many chunks around player are "active".
# Default: 10 → Decrease to 4-6
# This is THE most important setting!
simulation-distance=4
# View distance: How many chunks player can SEE
# Can stay high, players see far but world is only active close up
view distance=10
# Network compression: Balance between CPU and bandwidth
#256 is sweet spot
network-compression-threshold=256
# Spawn protection (unnecessary on survival)
spawn protection=0
# === CHUNK LOADING ===
# How many chunks around spawn point always remain loaded
# Decrease or 0 for lower RAM
spawn-chunk-radius=2
Why is simulation distance so crucial?
| Simulation Distance | Active Chunks | Mobspawns | CPU Usage | |----------|----------------|-----------|-------------| | 10 (default) | 441 chunks | Complete | 100% | | 6 | 169 chunks | 60% | 38% | | 4 | 81 chunks | 40% | 18% |
Going from 10 to 4 saves >80% CPU! Players barely notice this (farms slightly slower, mobs spawn closer).
2.2 purpur.yml (Advanced Purpur Options)
nanopurpur.yml
Performance Sections:
world settings:
default:
# === MOB AI OPTIMIZATION ===
mobs:
# Disable AI for specific mobs that contribute little
zombie:
ridable: false
aggressive-towards-villager-when-lagging: false
# Tropical fish do NOTHING but cost a lot of AI
tropical_fish:
ridable: false
takes-damage-from-water: false
# Axolotls spawn a lot but do little
axolotl:
ridable: false
# === REDSTONE ===
# Limit hopper checks (biggest cause of lag)
hopper:
disable-move-event: true
# === ENTITIES ===
# Merge dropped items (fewer entities)
merge radius:
item: 4.0
exp: 6.0
# Delete items faster
alt-item-despawn-rate:
enabled: true
items:
cobblestone: 300 # 15 sec (was 6000 = 5 min)
nether rack: 300
sand: 300
gravel: 300
# === VILLAGERS (CPU KILLERS) ===
villager:
# Limit how many villagers get AI per tick
lobotomize:
enabled: true
check interval: 100
# Disable brain ticking when far away
brain tricks: 2
# === CHUNK LOADING ===
# Async chunk loading (does not block main thread)
use-async-pathfinding: true
Pro tip - Lobotomize Villagers:
Lobotomize = "to make brain dead". Villagers who cannot pathfind (e.g. locked in trading hall) no longer receive AI after 100 ticks. They still work (trades, breeding), but cost 0% CPU. Huge boost for servers with trading halls.
2.3 spigot.yml (Spigot Optimizations)
nano spigot.yml
world settings:
default:
# === MOB SPAWN LIMITS ===
# By default, WAY too many mobs spawn
mob spawn range: 6 # Was 8, decrease = fewer mobs far away
entity activation range:
# How far mobs are "active" (AI running)
animals: 16 # Was 32
Samples: 24# Was 32
raiders: 48 # Was 48 (ok)
misc: 8 # Was 16
water: 8 # Wash 16 (fish/axolotls)
villagers: 16 # Was 32
flying monsters: 48 # Phantoms
# === TICK RATES ===
# How often to update certain systems
entity tracking range:
players: 48
animals: 48
samples: 48
misc: 32
# === GROWTH RATES ===
# Slow down crop/plant growth (fewer ticks)
growth:
cactus modifier: 150 # Was 100 (50% slower)
cane modifier: 150
melon modifier: 150
mushroom modifier: 150
pumpkin modifier: 150
sapling modifier: 150
beetroot modifier: 150
carrot modifier: 150
potato modifier: 150
wheat modifier: 150
# === HOPPER OPTIMIZATION ===
hopper transfer: 8 # Was 8 (ok)
hopper check: 1 # Was 1 (ok)
hopper-amount: 1 # How many items per transfer
# === MERGE SETTINGS ===
merge radius:
item: 4.0
exp: 6.0
Why increase growth modifiers?
Farms still work, but 50% slower. This saves a lot of CPU because block ticking (the check "should I grow?") happens less often. For casual servers you hardly notice this.
2.4 paper-world-defaults.yml (Paper Specific)
nano config/paper-world-defaults.yml
entities:
# === SPAWNING ===
spawning:
# Limit total number of entities
spawn limits:
ambient: 5 # Bats
axolotls: 3 # Axolotls (CPU killers)
creature: 8 # Animals
sample: 50# Samples
underground_water_creature: 3 # Glow squid
water_ambient: 15 # Pisces
water_creature: 3 # Dolphins/turtles
# === TICK RATES ===
# Per-mob spawning budget
per-player-mob-spawns: true
# === BEHAVIOR ===
behaviour:
# Disable AI for mobs far away
tick-inactive-villagers: false
# Zombies don't break doors (saves pathfinding)
zombie-villager-infection-chance: 50.0
chunks:
# === CHUNK SYSTEM ===
# Auto-save interval (higher = less IO lag)
auto-save interval: 6000 # Was 6000 (5 min is ok)
# Prevent chunk loading cascade (lag spike cause)
prevent-moving-into-unloaded-chunks: true
# Max chunks per tick
max-auto-save-chunks-per-tick: 8
Step 3: Java Startup Flags (Aikar's Flags)
3.1 Why Standard Java is Bad
Default java -jar server.jar uses old garbage collector (GC) which:
- Every 30-60 seconds server freezes for 500-2000ms
- Uses memory inefficiently
- Causes "lag spikes" where players DC
3.2 Aikars Flags: The Gold Standard
These flags were developed by Aikar (Minecraft performance expert) and tested on thousands of servers.
For 4GB RAM server:
java -Xms4G -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 purpur.jar nogui
For 6GB RAM server:
Replace -Xms4G -Xmx4G with -Xms6G -Xmx6G
For 8GB+ RAM server (ZGC variant):
java -Xms8G -Xmx8G\
-XX:+UseZGC \
-XX:+ParallelRefProcEnabled \
-XX:+UnlockExperimentalVMOptions\
-XX:+DisableExplicitGC \
-XX:+AlwaysPreTouch \
-XX:ZCollectionInterval=5 \
-XX:ZAllocationSpikeTolerance=2.0 \
-Dusing.aikars.flags=https://mcflags.emc.gs \
-jar purpur.jar nogui
ZGC (Z Garbage Collector) is even better for 8GB+ servers: GC pauses <10ms (totally unnoticeable).
3.3 Create a Startup Script
nanostart.sh
#!/bin/bash
# Aikar's flags for 4GB
java -Xms4G -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 purpur.jar nogui
chmod +x start.sh
./start.sh
Step 4: Performance Mods (Essential for 1.21)
4.1 Lithium - Server Side Performance
What does Lithium do?
Optimizes virtually all Minecraft systems without changing gameplay:
- Mob AI pathfinding (50% faster)
- Block ticking (crops, redstone)
- Chunk loading
- Physics calculations
Installation:
# Download from Modrinth
cd /opt/minecraft-server/mods
wget https://cdn.modrinth.com/data/gvQqBUqZ/versions/latest/lithium-fabric-mc1.21.jar
# Or for Paper/Purpur (via plugin wrapper):
# Lithium does NOT work directly on Paper, but you have Lithium features via Purpur configs
⚠️ Important: Lithium is a Fabric mod. For Paper/Purpur servers you already have the optimizations via Purpur's code (based on lithium patches).
4.2 FerriteCore - RAM Optimization
What does FerriteCore do?
Reduces RAM usage by 30-40% through more efficient data structures. Essential for modded or 4GB servers.
Download:
cd /opt/minecraft-server/mods
wget https://cdn.modrinth.com/data/uXXizFIs/versions/latest/ferritecore-7.0.0-fabric.jar
Result: 4GB server with 10 players now uses ~2.8GB instead of 3.8GB = more space for chunks.
4.3 Krypton - Network Optimization
Optimizes how the server sends packets to clients. Especially useful with 15+ players.
wget https://cdn.modrinth.com/data/fQEb0iXm/versions/latest/krypton-0.2.8-fabric.jar
4.4 For Modded Servers (Forge/NeoForge)
If you are running a modded server (All the Mods, FTB, etc.):
Essential Performance Mods:
| Mod | Function | Link | |-----|---------|------| | ModernFix | General optimizations | modrinth.com/mod/modernfix | | FerriteCore | RAM reduction | modrinth.com/mod/ferritecore | | EntityCulling | Render optimization | modrinth.com/mod/entityculling | | Canary | Lithium for Forge | modrinth.com/mod/canary | | Roadrunner | Async chunk loading | modrinth.com/mod/roadrunner |
Step 5: Monitoring and Diagnostics
5.1 Spark - Performance Profiler
Installation:
cd /opt/minecraft-server/plugins
wget https://ci.lucko.me/job/spark/lastSuccessfulBuild/artifact/spark-bukkit/build/libs/spark-bukkit.jar
In-game use:
/spark profiler starts
# Let server run for 2-3 minutes
/spark profiler stop
/spark profiler open
You will receive a web link with detailed analysis:
- Which plugins/mods cost the most CPU
- Which chunks cause lag
- Entity counts per chunk
5.2 Timings - Built-in Diagnostics
/timingson
# Wait 10 minutes
/timingspaste
Returns report with:
- TPS history -Plugin performance
- Entity activity
Read timings report:
Look for red bars in the report:
Entity Tickhigh → Too many entities, increase despawn ratesTile Entityhigh → Too many hoppers/chests, optimize redstoneWorld Tickhigh → Simulation distance too high
5.3 TPS Command
Check real-time TPS:
/tps
Output:
TPS from last 1m, 5m, 15m: 19.8, 19.9, 20.0
Good: >19.5 consistent Moderate: 17-19 (noticeable lag) Bad: <17 (unplayable)
Step 6: Hardware Considerations (VPS Selection)
6.1 RAM Requirements
| ServerType | Players | Mods | Minimum RAM | Recommended RAM | |-------------|---------|------|-------------|----------------| | Vanilla 1.21 | 1-10 | None | 2GB | 4GB | | Vanilla 1.21 | 10-20 | None | 4GB | 6GB | | Vanilla 1.21 | 20-50 | None | 6GB | 8GB | | Light Modpack | 1-10 | 50-100 | 4GB | 6GB | | Heavy Modpack | 1-10 | 150+ | 6GB | 8-12GB | | ATM9/FTB | 1-5 | 300+ | 8GB | 12-16GB |
6.2 CPU Requirements
Clock speed > Core count for Minecraft (single-threaded game logic).
| VPS Spec | Max Players (Vanilla) | TPS Forecast | |----------|----------------------|-----------------| | 2 cores @ 2.4 GHz | 5-8 | 18-19 TPS | | 2 cores @ 3.0 GHz+ | 10-15 | 19-20 TPS | | 4 cores @ 3.0 GHz+ | 15-25 | 20TPS | | 6 cores @ 3.5 GHz+ | 25-40 | 20TPS |
Space Node Recommendations:
- Budget (€10-15/month): 4GB RAM, 2 cores → Perfect for 5-10 players
- Standard (€20-25/month): 6GB RAM, 4 cores → Good for 10-20 players
- Pro (€35-50/month): 8-12GB RAM, 4-6 cores → Heavy modpacks or 20+ players
6.3 Storage: NVMe vs SSD vs HDD
| Type | Chunk Load Time | Auto save Lag | Price | |------|----------------|---------------|-------| | HDD | 500-1000ms | Noticeable freezes | Cheap | | SSD | 50-100ms | Little hickup | Standard | | NVMe | 10-30ms | Unnoticeable | Premium |
For Minecraft: NVMe is significantly better. Chunk loading is I/O intensive. Space-Node VPS uses NVMe standard.
Step 7: Troubleshooting Specific Problems
Problem: Lag Spikes every 30 seconds
Cause: Java Garbage Collection with bad flags
Diagnosis:
# Add to startup flags
-XX:+PrintGCDetails -Xlog:gc*:file=gc.log
Check gc.log. If you see:
[Full GC (Allocation Failure) 2048M->1800M(2048M), 2.1 secs]
This is a 2+ second freeze. Solution: Use Aikar's flags.
Problem: High RAM usage (server crashed)
Diagnosis:
# In-game command
/forge entity list
# Or via Spark
/spark heap dump
Common causes:
-
Too many entities in spawn chunks
- Fix: Reduce
spawn-chunk-radiusto 0-2
- Fix: Reduce
-
Mob farm overload
- Solution: Limit entities with
entity-activation-range
- Solution: Limit entities with
-
Memory leak in plugin/mod
- Solution: Check Spark heap dump, disable suspicious plugin
Problem: Server "Can't keep up" warnings
Console output:
[WARN] Can't keep up! Is the server overloaded? Running 5000ms behind, skipping 100 ticks
This means: The server could not complete one tick in 50ms, so it skips ticks = rubberband lag.
Top 3 causes:
-
Simulation distance too high
- Reduce to 4
-
Redstone lag (hoppers, observers)
- Use
/spark→ find chunks with many tile entities
- Use
- Optimize with water streams instead of hoppers
- Not enough CPU
- Upgrade VPS or reduce player limit
Step 8: Basic Configuration Checklist
Print this checklist and check off:
server.properties:
- [ ]
simulation-distance=4(or max 6) - [ ]
view-distance=10 - [ ]
network-compression-threshold=256
purpur.yml:
- [ ]
villager.lobotomize.enabled=true - [ ]
merge-radius.item=4.0 - [ ]
alt-item-despawn-rate.enabled=true
spigot.yml:
- [ ]
mob-spawn-range=6 - [ ]
entity-activation-rangereduced - [ ]
hopper-transfer=8
Start script:
- [ ] Aikar's flags used
- [ ] RAM setting correct (-Xms and -Xmx same)
- [ ] Java 21 (Temurin/Adoptium)
Performance mods:
- [ ] Lithium/Purpur optimizations
- [ ] FerriteCore (as modded)
Monitoring:
- [ ] Spark plugin installed
- [ ]
/tpscheck after each change
Result: Before and After Optimization
Example Case: 10 Player Survival Server
| Metric | For (Vanilla) | After (Purpur + Configs) | Improvement | |--------|----------------|----------------------|-------------| | TPS | 14-16 | 19.8-20 | +25-40% | | MSPT | 65-80ms | 45-50ms | -30% | | RAM usage | 3.8GB | 2.6GB | -30% | | Chunk load time | 800ms | 150ms | -80% | | Lay spikes | Every 30sec | None | -100% |
Player experience:
- ✅ No rubber band
- ✅ Instant chunk loading
- ✅ Fluid combat
- ✅ No disconnects due to lag
Conclusion: From Laggy Server to Fluid Experience
By following this guide you will transform a Minecraft 1.21 server from unusable to professional level:
- ✅ Purpur for best performance baseline
- ✅ Simulation distance 4-6 for 80% less CPU
- ✅ Aikar's JVM flags for stable garbage collection
- ✅ Targeted config tuning for every aspect
- ✅ Performance mods where necessary
- ✅ Monitoring tools to find problems
Time investment: 1-2 hours setup, lifetime benefits.
Ready to run an optimized Minecraft server? Space-Node VPS hosting offers NVMe servers specifically tailored to Minecraft, with pre-configured Purpur setups available. From €10/month with 24/7 support. Related guides:
