Minecraft Server Tick Skipping & Lag Spike Diagnosis: How to Find the Root Cause Fast
# Minecraft Server Tick Skipping & Lag Spike Diagnosis: How to Find the Root Cause Fast
Your server runs at a smooth 20 TPS for hours — then suddenly drops to 8 TPS for five seconds, players rubberband, entities freeze, and everything goes back to normal. Sound familiar?
These are lag spikes, and they are one of the most frustrating performance issues to debug. Unlike constant low TPS (which usually has an obvious cause), lag spikes are intermittent, hard to reproduce, and easy to misdiagnose. This guide gives you a systematic method to find the real root cause — fast.
---
What Is Tick Skipping?
Minecraft's server loop runs once every 50 milliseconds (20 ticks per second). When a single tick takes longer than 50ms to process, the server falls behind. If the overrun is severe enough, Minecraft logs a warning:
Can't keep up! Is the server overloaded? Running 200ms or 2 ticks behind
This is tick skipping — the server didn't skip anything, it just took too long on one or more ticks. The result is perceived lag: movement stutter, delayed interactions, and mob AI freezing briefly.
---
Step 1: Distinguish Spike Types
Before you fix anything, categorize your spike:
| Spike Type | Duration | Likely Cause |
|---|---|---|
| Short spike | < 200ms | Chunk load, GC pause, sudden entity burst |
| Medium spike | 200ms–2s | Plugin tick, world save, heavy redstone |
| Long spike | 2s–10s+ | Disk I/O stall, memory pressure, terrain gen |
| Periodic spike | Every X minutes | Scheduled tasks, auto-save, plugin timers |
If your spikes happen at regular intervals, check your auto-save setting first:
bukkit.yml
ticks-per:
autosave: 6000
The default is 6000 ticks (5 minutes). On servers with large worlds, increasing this to 12000 or even 18000 and relying on an async save plugin can eliminate periodic spikes entirely.
---
Step 2: Use Spark to Capture Spikes
[Spark](https://spark.lucko.me/) is the gold standard for Minecraft profiling. Install it as a plugin, then use sampler mode to catch what's happening during a spike:
/spark sampler --timeout 120
This runs a 2-minute profiler. Trigger the spike (or wait for it), then view the report. Look for:
- Methods consuming > 10% of tick time that aren't vanilla Minecraft
- Plugin names appearing near the top of the call stack
CraftSchedulerentries indicating async tasks bleeding into the main thread
For spike-only profiling, use the health monitoring feature:
/spark healthreport
This gives you a snapshot of GC activity, CPU load, and TPS history — invaluable context when reviewing a spike after the fact.
---
Step 3: Isolate Chunk-Related Spikes
Chunk loading is one of the most common spike sources. When a player moves into an unloaded area, the server must:
- Read the chunk from disk
- Deserialize NBT data
- Tick all entities and block entities in that chunk
- Send chunk packets to nearby players
All of this can stall the main thread. In paper-world.yml, tune these settings:
chunks:
max-auto-save-chunks-per-tick: 8
prevent-moving-into-unloaded-chunks: true
entity-per-chunk-save-limit:
experience_orb: 16
snowball: 8
arrow: 16
Also ensure you are using async chunk loading, which Paper enables by default. If you're on Spigot without Paper, consider migrating — this single feature alone eliminates a large category of chunk-load spikes.
---
Step 4: Check for Plugin Scheduler Abuse
Many plugins register repeating tasks that run every tick or every few ticks unnecessarily. Open your Spark report and look at the CraftScheduler section. If a plugin is running heavy logic synchronously every tick, you'll see it clearly.
You can also use the /timings command (Paper/Spigot built-in) for a lighter-weight view:
/timings reset
/timings report
Wait through a spike, then generate the report. Look at Worst-case tick entries — these show the maximum time a section consumed in a single tick, not just the average.
Common offenders:
- Economy plugins recalculating balances every tick
- Protection plugins checking regions on every block update
- Custom NPC plugins running pathfinding logic too frequently
---
Step 5: Diagnose GC-Induced Spikes
Java's garbage collector can pause all threads, including the main server thread. These stop-the-world pauses manifest as clean, hard spikes with no obvious in-game cause.
To check if GC is responsible, add this JVM flag to your startup script:
-Xlog:gc*:file=gc.log:time,uptime:filecount=5,filesize=10m
Then open gc.log after a spike and look for Pause Full events longer than 100ms. If you find them, your GC tuning needs attention — specifically ensure you're using Aikar's flags or G1GC with proper region sizing.
If you're using PulseNode to monitor your server, the metrics dashboard can help you correlate TPS drops with memory usage graphs, making it much easier to confirm a GC spike versus a plugin spike without digging through logs manually.
---
Step 6: World Save Stalls
Even with async saving enabled, some servers experience stalls when the save queue becomes too large. In paper-world.yml:
chunks:
max-auto-save-chunks-per-tick: 8
Lowering this from the default spreads the save load across more ticks. Alternatively, use a plugin like ChunkSaver or configure server.properties:
level-type=minecraft:normal
Make sure you're not running custom terrain generators that block the save thread — some older generators are not async-safe.
---
Step 7: Entity & NBT Load Spikes
When a chunk loads that contains thousands of items in a chest (or thousands of entities), deserializing all that NBT data can stall the server for hundreds of milliseconds.
In paper-world.yml, use per-chunk entity limits to prevent this from getting out of hand:
entity-per-chunk-save-limit:
item: 32
experience_orb: 16
arrow: 16
fireball: 8
For item frames, paintings, and armor stands, set reasonable per-chunk limits in spigot.yml:
world-settings:
default:
item-despawn-rate: 6000
merge-radius:
item: 2.5
exp: 3.0
---
Step 8: Build a Spike Log
Once you've identified candidate causes, keep a structured log:
- Timestamp of the spike
- Duration in ms
- TPS before and after
- Player count at the time
- Recent activity (new area explored, item farm active, etc.)
Patterns often emerge after 10–20 entries. Spikes that always happen when player count crosses 30 suggest a different root cause than spikes that happen at exactly 12:00 AM.
---
Summary: Spike Diagnosis Checklist
- [ ] Check
bukkit.ymlautosave interval - [ ] Profile with
/spark samplerduring a spike - [ ] Review
/timings reportfor worst-case tick times - [ ] Enable GC logging and check for stop-the-world pauses
- [ ] Tune
paper-world.ymlchunk save limits - [ ] Set entity-per-chunk save limits to prevent NBT bloat
- [ ] Review plugin scheduler tasks for synchronous abuse
---
Diagnosing lag spikes manually takes time, but the systematic approach above will get you to the root cause far faster than guessing. If you want a continuous view of your server's TPS, memory, and CPU over time without having to run manual profilers, [PulseNode](https://pulsenode.tech) provides real-time monitoring dashboards that make spike patterns visible at a glance — so you can spend less time hunting and more time fixing.