Short answer
Optimize in this order: JVM flags, then the configuration values that reduce tick work, then pre-generation so nobody generates chunks during play, then plugins. Measure with spark before and after each stage, because the bottleneck moves as you fix it.
Optimizing a server is a sequence, not a checklist. Start with the biggest lever, measure, and let the profile tell you the next one. People who skip the measurement end up tuning the wrong thing confidently for a week.
This guide is that sequence for a Paper server on modest hardware: the start command, the configuration changes, pre-generating the map, and the plugin pass. Each stage assumes the previous one is already done and measured.
Before you start
- File access to the server root
- Spark, which Paper bundles or you can install
- A spare half hour per stage, and a backup before you start
1. Start from a profile, not an opinion
Install spark if it is not already there, let the server run through a normal session, and take a profile while the problem is happening. The report ranks what is using tick time: chunk generation, entity ticking, a particular plugin, hoppers, redstone.
That ranking decides what you do next. If chunk generation is at the top, pre-generation is the answer. If a plugin is, no amount of flag tuning will touch it.
/spark profiler start
# let it run through a session
/spark profiler stop2. Set the JVM flags Paper documents
The garbage collector matters more than most people expect on small servers. Paper publishes a set of G1 flags tuned for Minecraft's allocation pattern and uses them in its own start script. Copy them from the Paper documentation rather than from a forum post, and set -Xms equal to -Xmx so the heap never has to resize while players are on.
Leave memory for the system. Paper's guidance is to subtract roughly 1000 to 1500 MB from your total RAM for the JVM and the operating system, so a host that gives you 8 GB should get about -Xmx6G rather than 8. The memory guide covers this in detail.
java -Xms6G -Xmx6G -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 paper.jar --nogui3. Remove tick work from the configuration
Now the config. Entity spawn caps and despawn ranges decide how much mob logic runs; view distance and simulation distance decide how many chunks exist and how many entities move; collision limits decide how many pairs are checked. Each of these is a multiplier on work that happens every tick.
Set them from the settings guide, restart, and profile again. The report should have moved: whatever was at the top before is now smaller, and something else is now visible at the top. That new entry is your next stage.
entity:
spawning:
spawn-limits:
monsters: 40
per-player-mob-spawns: true
chunks:
entity-per-chunk-save-limit:
experience_orb: 16
collisions:
max-entity-collisions: 4
only-players-collide: true4. Pre-generate the map so nobody generates it in play
Generating a chunk is the most expensive single thing a server does per tick, and it happens on the main thread while a player waits. If the profile shows chunk generation high, that is players walking into unexplored territory.
Two fixes. Pre-generate the area the world will cover with a plugin such as Chunky, running offline when nobody is on, so the work is done once. Then set a world border at the edge of the generated map, so players cannot walk past it and generate more than you prepared.
/chunky radius 5000
/chunky startmax-world-size=100005. Trim the plugin list and confirm
Plugins are the last stage because they are the easiest to change without consequence. Every plugin costs memory on startup and tick time for whatever it does every second, whether or not players are using it. Remove what you do not use, and check the profile for what remains.
Take the final /tps and /mspt readings with the same number of players as the first profile and compare. Then stop. Past a steady 20.0 with tick headroom to spare, further optimization buys nothing you can feel, and the memory guide has the sizing question if the answer is "we need more hardware".
Good to know
- Optimize in stages with a measurement between each. A stage with no measurement is a change you will never be able to justify or undo.
- Pre-generation is the single most effective change on a survival server whose players explore in a straight line. It costs disk space, not RAM, and the work happens once.
- Separate play and world-generation work is the reason mods like Fabric exist on the client; on the server side there is no such split, which is why pre-generating helps so much.
- Not every lag is tick work. A network problem shows up as rubber-banding with a perfect
/tps, and no amount of configuration changes that. The general lag guide starts with that distinction.
Common questions
What is the fastest way to make Paper faster?
Lower the entity spawn caps and view distance, then pre-generate the world so players do not generate chunks in play. On a small server those three changes usually move the profile more than any JVM flag.
Do Paper need Aikar's flags?
The flags Paper publishes are tuned for Minecraft's allocation pattern and are what Paper's own start script uses. If you host the server yourself, use them. If you use a panel or host, the start command is already set for you and overriding it can break the platform's memory accounting.
Should I pre-generate my world?
If players explore new territory regularly, yes. Run it offline with a plugin such as Chunky, then set a world border so nobody generates beyond what you prepared. If your world is small and fully explored already, there is nothing to gain.
How do I know when to stop optimizing?
When /tps is a steady 20.0 with MSPT well below 50 during your busiest sessions. That is the point where the tick loop has headroom, and further changes are indistinguishable to players.
Sources
Official documentation this guide was checked against.
Rather not run this on your own machine? PufferHost gives every player a free Minecraft server with 3 GB of RAM and 10 slots. Create a free server.