Your plan might show three cores and a panel graph sitting at thirty percent — and the game can still be stuttering. That is not a contradiction. It is what happens when the work that matters is confined to exactly one of those cores, and the graph is only ever telling you the average.
Why the world tick cannot just be spread across cores
Every tick, the server has to answer questions like: did this arrow hit that player, in what order did these two pistons fire, does this redstone update happen before or after that one. Those answers depend on a single, consistent view of the world at that instant — two threads updating the same chunk at once would produce results that depend on timing rather than on the game's rules, which is the definition of a bug players would eventually notice as items duplicating or falling through blocks that were there a moment ago.
Multithreading a shared, constantly-mutating world safely is one of the harder problems in engine design, and Mojang has not solved it for the core game loop — entities, physics and redstone still tick on one thread. That thread is what a /spark profiler report is measuring when it points at «the main thread», and it is the resource every other setting on your server is ultimately trying to protect.
Reading the panel's CPU number correctly
| Panel shows | Plan has | What it actually means |
|---|---|---|
| 33% | 3 vCores | One core is fully saturated. The other two are close to idle. |
| 100% | 3 vCores | Either every core is busy — chunk generation, plugin threads — or a single-core reading is being reported as if it were the whole allocation. |
| 12% | 8 vCores | One saturated core out of eight. The server can be at its absolute limit while this number looks calm. |
A plan with more vCores gives async work — chunk generation, some world saves, background plugin tasks — more room to run without competing with the main thread. It does not give the main thread itself more speed, because there is only one of it and it cannot be split. If tick time is the bottleneck, the number that matters is single-core clock speed and how little work you are asking that one thread to do — not core count.
What actually raises the ceiling
- Run a
/spark profilerreport during the lag, not afterIt shows exactly which plugin, which entity type or which world region is consuming the main thread's time. Guessing from the panel graph alone cannot do this.
- Cut what the profiler names
Fewer entities in the hot area, a replaced plugin, a smaller view or simulation distance — whichever the report points at specifically.
- Move to Paper-family software if you have not
It offloads real work — chunk loading, some lighting and pathfinding — off the main thread within the limits vanilla behaviour allows, which is the single biggest lever available before touching anything else.
Ten milliseconds of badly written plugin code running every tick is a fifth of the entire 50-millisecond budget the server has to finish a tick in, regardless of how many cores or how much memory sit unused. A single-threaded bottleneck has no capacity to borrow from anywhere else.