Symptoms: The server normally runs smoothly, but every so often there are 2–5 second freezes and then it carries on. Players get momentarily "teleported", mobs jump around. These sudden freezes (lag spikes) usually come from a GC pause, a chunk save or a backup.

Possible Causes

  • Stop-the-world GC pause — the heap size is unsuitable or GC flags are missing
  • Chunk save spike — during an automatic save every modified chunk is written to disk at once
  • A backup is running — while tar/zip works the disk IO fills up and the main thread waits to write
  • RAM swap — physical RAM is not enough, so the kernel swaps to disk
  • A non-async plugin operation — a DB query or HTTP request blocking on the main thread
  • Entity / tile entity tick spike — too many hoppers or beacons processed in the same tick

Step-by-Step Fix

Step 1

Catch the moment of the spike with the Spark profiler — filter for the heavy ticks only

bash
/spark profiler --only-ticks-over 50 --timeout 180

Step 2

Turn on GC logs — see the pause durations clearly

bash
# add this to the start script:
-Xlog:gc*:file=logs/gc.log:time,uptime:filecount=5,filesize=10M

Step 3

Keep the heap fixed with Xms = Xmx. Also give it a MaxGCPauseMillis=200 target

bash
-Xms8G -Xmx8G -XX:+UseG1GC -XX:MaxGCPauseMillis=200

Step 4

Apply Aikar's Flags in full. Half of them will not end the spikes. Use the whole set

bash
# Reference for Aikar flags:
# https://docs.papermc.io/paper/aikars-flags

Step 5

Spread the chunk save out — do not save the whole world at once

bash
# config/paper-global.yml
chunk-saving:
  max-chunks-to-save-per-tick: 4

Step 6

Move your backup script to a low-traffic hour (03:00 for instance). Running tar while players are online causes a big spike

bash
crontab -l | grep backup
# new schedule example:
# 0 3 * * * /opt/scripts/mc-backup.sh

Step 7

Check RAM swap usage — if swap > 0 there is a problem

bash
free -m
vmstat 1 5  # si/so columns should be 0

Step 8

Reduce hopper chains and beacon clusters. Install LagAssist / FarmLimiter if you need to

bash
# Find the problem chunks in the Entity tick section of the Spark profiler report

Step 9

Watch out for non-async plugin operations — they show up in the Spark timings report. Either update the plugin or ask for a ConnectionPool to be added

Step 10

If the problem persists, upload the profile report to the KEYDAL Spark Analyzer tool; you get a free automated analysis: /oyun/araclar/spark