Minecraft Field guide

Why your Minecraft server lags and how to find the cause with spark

Separate Minecraft network latency from simulation lag, interpret TPS and MSPT, profile with spark and check server memory.

Why your Minecraft server lags and how to find the cause with spark

Capture the lag while it happens, identify the work consuming the game thread, and test one change against a second capture. This workflow uses Paper with spark and separates slow world simulation from a player's network or frame-rate problem.

Identify which part is falling behind#

Ask players whether the same freeze happened at the same time. A shared pause while breaking blocks or running a farm suggests a server-side problem; one player's stutter needs a connection and FPS check before server tuning.

At the ordinary game speed, the target is 20 TPS and the tick budget is 50 ms. MSPT measures time spent processing ticks: look at the median, 95th percentile and maximum rather than one average. A healthy TPS average can hide a brief stall. spark's metrics guide explains these readings.

Choose the first investigation from the symptom. The branches suggest what to measure; none proves the cause by itself.
ObservationFirst measurementWhat it can separate
Everyone slows down and MSPT risesProfile during that workloadEntity simulation, world generation or plugin work
Everyone briefly freezes, average TPS stays near 20Long-tick capture with timestampsShort stalls hidden in the average
Only one player strugglesThat player's ping, connection and FPSNetwork delay versus local rendering
Minecraft disappears or restartsService and kernel logsJVM failure, OS memory pressure or a scheduled restart

High ping and slow simulation can occur together. Do not conclude that one metric rules the other out.

Capture the workload that actually lags#

Paper bundles spark starting with 1.21. Older Paper releases and other server platforms may require a compatible plugin or mod. Use an operator account or the appropriate spark permissions.

In Minecraft chat, run:

text
/spark tps
/spark ping
/spark gc
/spark profiler start --timeout 600

This records a ten-minute profile and returns a report link. Reproduce the triggering activity during the capture: explore new chunks, activate the farm or join with the affected group. Save the time, player count and action alongside the link. A capture of an empty, idle server cannot explain an evening load spike.

If a profile is already running, check /spark profiler info; use /spark profiler open to view it or /spark profiler stop to finish it before starting another. Console commands omit the leading /. The command reference documents this syntax. Commands were source-checked on October 12, 2026; this article does not present a captured production profile.

Read the work, not just the largest percentage#

Open Server thread in the viewer, then expand the branches doing game work. Follow substantial branches down to useful class or method names. Names vary between Minecraft releases, so identify the operation rather than hunting for a fixed label from an old screenshot.

Percentages describe the sampled thread's time, not the entire VPS. A parent's total includes its descendants; adding those percentages double-counts work. Sleeping or parked time can mean the thread has finished its work and is waiting. For plugin-specific work, inspect the Sources view. These distinctions are documented in the spark viewer guide.

Turn the branch into an experiment:

Substantial work in the profileNext comparisonCandidate change if the result agrees
Chunk generationSame players at an existing base versus exploring new terrainLimit simultaneous exploration or evaluate pregeneration
Entities or block entitiesSame activity with the suspected farm unloaded or pausedReduce that farm's active workload
A plugin's scheduled taskA preserved server copy with that one plugin disabledAdjust its schedule/configuration or replace it
No clear game-work bottleneckFreeze timestamps versus host and GC activityInvestigate memory, I/O or VM scheduling before changing gameplay

The table gives hypotheses, not diagnoses from an unseen report. Disable plugins on a copy with a backup, use a full stop/start, and keep the same reproduction steps. Removing several plugins at once makes the result harder to interpret.

Catch isolated long ticks#

If the complaint is a short freeze rather than sustained slowdown, first finish the general profile, then run:

text
/spark tickmonitor --threshold-tick 100
/spark profiler start --only-ticks-over 100 --timeout 600

The example captures ticks longer than 100 ms; lower the threshold if the troublesome ticks are shorter. It is a capture filter, not a target for acceptable performance. Disable the monitor afterwards by running /spark tickmonitor once. This follows spark's lag-spike workflow.

Compare reported times with world saves, backup jobs and periodic plugin tasks. If there is a correlation, move or disable one scheduled task in a controlled test and capture again. An empty filtered report may simply mean the problem did not occur or the threshold was too high.

Check memory pressure and restarts on the VPS#

-Xmx limits the Java heap. The process also uses native memory, while the OS and other applications need their own share. On the Linux VPS, run these during the episode:

bash
free -h
vmstat 1 10
df -h

In free, inspect available: Linux can reclaim part of its cache, so a low free value alone does not establish a shortage. In vmstat, compare subsequent rows with the lag timestamps; the first row averages activity since boot. Repeated si/so activity means pages are moving to/from swap and warrants a memory-pressure investigation. The free and vmstat manuals define these fields.

df checks capacity, not disk latency. If space is exhausted, fix that before collecting more profiles or backups. If the host is already short of RAM, increasing -Xmx can worsen competition. When GC pauses coincide with the freezes despite available host memory, investigate allocation pressure and the heap configuration; Oracle's G1 guidance is a better starting point than a copied list of JVM flags.

For the minecraft service from the Ubuntu installation guide, inspect the failure window:

bash
sudo systemctl show minecraft -p NRestarts -p Result
sudo journalctl -u minecraft --since '30 minutes ago' --no-pager
sudo journalctl -k --since '30 minutes ago' --no-pager

Substitute your service name if different. Look for OutOfMemoryError in the JVM log, an OOM-kill entry in the kernel log, watchdog errors or an explicit shutdown. These point to different failures. Restart counters and a missing process alone do not prove that the Java heap was too small.

Test one change under comparable conditions#

Save the original setting and the first report link. Change one cause suggested by the evidence, then repeat the capture with similar player counts and the same activity.

If world simulation dominates, reducing simulation-distance may reduce work but also affect distant farms. view-distance controls another part of the workload; consult the settings reference before using both as interchangeable tuning knobs. Record what players lose as well as what the timing gains.

If the game thread is still saturated, ask the provider about CPU performance or noisy-neighbour contention using the report and timings. A higher virtual-CPU count alone does not show that this thread will run faster.

Nexardo's panel for your own VPS can be considered when organizing administration. Choose workload or hardware changes from the measurements above; a management panel is not a performance benchmark.

For a support request, include the profile link, episode time, Minecraft/Paper/Java versions, plugin list, heap settings, player count, reproduction steps and the one change already tested. Review the report and remove secrets and player addresses from logs before sharing. This gives the next person a workload to investigate rather than a request to guess a RAM size.

References#