Minecraft 1.21 Lag Fix: Complete Server Optimization Guide 2026

Published on

Fix your Minecraft 1.21+ server lag with this complete optimization guide. Paper vs Purpur configuration, JVM flags (Aikar), performance mods (Lithium, FerriteCore), and simulation distance tuning. From unplayable to smooth 20 TPS.

Written by Jochem, CEO of Space-Node, 5-10 years experience in game server hosting, VPS infrastructure, and 24/7 streaming solutions. Read author bio →

minecraft 1 21 fix lag server optimization 2026

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:

ChangeImpact on PerformancePercentage of Additional CPU
Trial Chambers (new structure)Complex generation with many entities+15-25%
Breeze mobAdvanced AI with pathfinding+10% on spawning
Wind ChargesAdditional projectile physics+5-10% in combat
Higher build limitMore chunks to track+5-15%
Copper/Tuff variantsMore 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
  • under 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

FeatureVanillaPaperPurpur
Async chunk loading
Mob AI optimizationBasicAdvanced
Config optionsLittleMuchVery much
Entity activation rangeStaticDynamic
Redstone Optimizations✅+
Disable per-mob AI
Gameplay featuresBasicBasicExtensive

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 DistanceActive ChunksMobspawnsCPU Usage
10 (default)441 chunksComplete100%
6169 chunks60%38%
481 chunks40%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 under 10 ms (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:

ModFunctionLink
ModernFixGeneral optimizationsmodrinth.com/mod/modernfix
FerriteCoreRAM reductionmodrinth.com/mod/ferritecore
EntityCullingRender optimizationmodrinth.com/mod/entityculling
CanaryLithium for Forgemodrinth.com/mod/canary
RoadrunnerAsync chunk loadingmodrinth.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 Tick high → Too many entities, increase despawn rates
  • Tile Entity high → Too many hoppers/chests, optimize redstone
  • World Tick high → 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: under 17 (unplayable)


Step 6: Hardware Considerations (VPS Selection)

6.1 RAM Requirements

ServerTypePlayersModsMinimum RAMRecommended RAM
Vanilla 1.211-10None2GB4GB
Vanilla 1.2110-20None4GB6GB
Vanilla 1.2120-50None6GB8GB
Light Modpack1-1050-1004GB6GB
Heavy Modpack1-10150+6GB8-12GB
ATM9/FTB1-5300+8GB12-16GB

6.2 CPU Requirements

Clock speed > Core count for Minecraft (single-threaded game logic).

VPS SpecMax Players (Vanilla)TPS Forecast
2 cores @ 2.4 GHz5-818-19 TPS
2 cores @ 3.0 GHz+10-1519-20 TPS
4 cores @ 3.0 GHz+15-2520TPS
6 cores @ 3.5 GHz+25-4020TPS

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

TypeChunk Load TimeAuto save LagPrice
HDD500-1000msNoticeable freezesCheap
SSD50-100msLittle hickupStandard
NVMe10-30msUnnoticeablePremium

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:

  1. Too many entities in spawn chunks

    • Fix: Reduce spawn-chunk-radius to 0-2
  2. Mob farm overload

    • Solution: Limit entities with entity-activation-range
  3. 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:

  1. Simulation distance too high

    • Reduce to 4
  2. Redstone lag (hoppers, observers)

    • Use /spark → find chunks with many tile entities
  • Optimize with water streams instead of hoppers
  1. 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-range reduced
  • 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
  • /tps check after each change

Result: Before and After Optimization

Example Case: 10 Player Survival Server

MetricFor (Vanilla)After (Purpur + Configs)Improvement
TPS14-1619.8-20+25-40%
MSPT65-80ms45-50ms-30%
RAM usage3.8GB2.6GB-30%
Chunk load time800ms150ms-80%
Lay spikesEvery 30secNone-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:

  1. Purpur for best performance baseline
  2. Simulation distance 4-6 for 80% less CPU
  3. Aikar's JVM flags for stable garbage collection
  4. Targeted config tuning for every aspect
  5. Performance mods where necessary
  6. 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 12/7 support. Related guides:

Jochem

About the Author

Jochem, CEO of Space-Node, expert in game server hosting, VPS infrastructure, and 24/7 streaming solutions with 5-10 years experience.

Since 2023
500+ servers hosted
4.8/5 avg rating

I specialize in Minecraft, FiveM, Rust, and 24/7 streaming infrastructure, operating enterprise-grade AMD Ryzen 9 hardware in Netherlands datacenters.

View my full bio and credentials →

Start Your MC Server Now Today

Join content creators worldwide who trust our Minecraft infrastructure. Setup is instant and support is always available. Start from €0.90/mo (Dirt) or €2.70/mo (Coal) and go live in minutes.