“Minecraft is single-threaded” is one of the most repeated claims in server administration communities, and it is both true and misleading at the same time. It is true of one specific piece of the server: the main tick loop, which handles block updates, entity AI, and player interaction. It is false of most of the rest of the server’s workload, which Mojang has moved off the main thread over several major versions. Conflating the two leads admins toward the wrong fix: buying a CPU with more cores when the actual bottleneck is single-core clock speed, or chasing a “multithreading mod” for Forge that cannot exist for architectural reasons explained below.
This post lays out what actually executes where, what Folia and ShreddedPaper change, and why neither is a drop-in fix for a modded server.
What the main tick loop actually is
A vanilla or Paper server runs a loop that targets 20 ticks per second, one tick every 50ms. Each tick, the server processes:
- Block updates (placement, breaking, redstone propagation, fluid flow)
- Entity AI and physics (pathfinding decisions, movement, collision)
- Player input processing (movement, interactions, inventory actions)
This loop runs on a single thread because the systems inside it are tightly interdependent within the same tick. A zombie’s pathfinding decision depends on which blocks currently exist. A player breaking a block can invalidate an in-flight AI decision for a mob standing on it. An Enderman picking up a block and a player breaking that same block in the same tick is a race condition if left unsynchronized. Keeping this logic on one thread is what lets Minecraft guarantee that block state, entity state, and player actions are always consistent within a tick, without a locking system between every subsystem.
This is also why community suggestions like “just multithread Forge” are not requests for a missing feature; they are requests to solve a genuinely hard concurrency problem inside a game engine that was never designed with parallel tick logic in mind.
What is not single-threaded
Mojang has moved substantial parts of server workload off the main thread over the years:
- Chunk generation: worldgen work happens on background worker threads. This is documented through community observation of thread dumps (crash reports have shown dedicated “WorldGen-Worker” threads, sometimes numbering in the dozens on busy servers) rather than a specific Mojang changelog entry, so treat the exact version boundary as approximate rather than an official cutoff.
- Lighting: light engine calculations run off the main thread, avoiding the tick-time cost of recalculating light levels synchronously during world changes.
- Networking: Paper and Spigot run network I/O through Netty on its own thread pool, separate from the tick loop. This is why a spark profile run with
--thread *can show packet processing as a distinct hotspot from main-thread work, and why increasing Netty thread count inspigot.ymlis a real (if narrow) lever when packet handling itself is the bottleneck, not the tick loop. - Async chunk loading and saving: Paper loads and saves chunk data asynchronously so disk I/O does not block the tick loop.
None of this changes the fact that block placement, entity AI, and player-facing game logic still funnel through the single main tick loop. Multithreaded chunk generation makes the world load faster; it does not make a redstone-heavy tick any cheaper.
Folia: splitting the tick loop itself, region by region
Folia, a Paper fork maintained by PaperMC, is the first project to multithread the tick loop itself rather than just the work around it. Instead of one global tick loop, Folia groups nearby chunks into independent regions, and each region gets its own tick loop running at the standard 20 TPS target, executed in parallel across a thread pool. A large SMP or Skyblock server with players spread across the map effectively gets N independent single-threaded servers running concurrently, one per region, instead of one shared bottleneck.
The technical model is stricter than that summary suggests. Per PaperMC’s own documentation, Folia enforces region safety through four invariants: every chunk belongs to exactly one live region, all chunks within a defined merge radius belong to the same region, a ticking region cannot expand which chunks it owns mid-tick, and every region is always in exactly one of four states (transient, ready, ticking, dead). When two regions’ areas of influence get close enough, they merge; when a region’s active area shrinks, it can split back into smaller regions. This is what lets two players on opposite sides of a large world tick fully in parallel without a lock between them, while two players standing near each other still safely share one region and one thread.
This has real costs:
- Plugin API is not backward compatible. PaperMC’s own words: “I expect every single plugin that exists to require some level of modification to function in Folia.” Plugins must explicitly opt in with
folia-supported: trueand rewrite any code that usedBukkitSchedulerto instead use one of four region-aware schedulers (global, region, async, entity), because a callback that assumes “the main thread” no longer has a single main thread to assume. - Some vanilla-adjacent APIs are simply broken as of this writing, including portal and respawn mechanics, scoreboard functionality, world loading/unloading, and
Entity#teleport. These are not edge cases; they are common enough that most plugin ecosystems need real porting work, not a config flag. - Hardware requirements are steep. PaperMC recommends at least 16 physical cores, not threads, for Folia to be worth running, plus pre-generated worlds, since on-the-fly generation competes with tick threads for CPU.
- Folia is not a general performance upgrade. It helps specifically when players are spread across a large world, like SMP or Skyblock. A small, geographically clustered playerbase gains little, because if everyone is standing near each other, they are all in the same region regardless of how many cores the machine has.
Folia is a genuine architectural answer to “make the tick loop parallel,” not a workaround. But it answers a specific problem (many players spread across a big world) and introduces a specific cost (an incompatible plugin ecosystem), rather than being a universal multithreading switch.
ShreddedPaper: a different tradeoff for a single server
ShreddedPaper, maintained by the MultiPaper project, takes a related but distinct approach: instead of independent per-region tick loops like Folia, it multithreads chunk ticking within what is still conceptually a single server, using a locking scheme rather than Folia’s region-ownership model. Per the project’s own technical documentation, chunks are grouped into regions and, critically, an entire region is locked during ticking rather than locking individual chunks. When one region is being ticked, its directly neighboring regions (a 3x3 grid around it) are also locked, which is what allows cross-boundary interactions, like redstone signals propagating into an adjacent region, to stay safe without a race condition.
The tradeoff embedded in that design: locking whole regions instead of individual chunks trades some potential parallelism for a much simpler, more tractable concurrency model. It is coarser-grained than theoretically optimal, but coarse-grained locking that is provably correct beats fine-grained locking that occasionally corrupts world state.
ShreddedPaper’s plugin compatibility story leans on Folia’s prior work: plugins already updated to support Folia’s region-aware scheduler APIs are reported to work on ShreddedPaper largely unchanged, since both projects converged on a similar region-based mental model for plugin authors. That does not mean ShreddedPaper has automatic compatibility with every existing plugin; it means the porting work Folia already forced onto the plugin ecosystem is largely reusable here, not that unmodified BukkitScheduler-based plugins are safe.
Why none of this touches Forge or Fabric
Every project discussed above, Folia and ShreddedPaper, is a fork of Paper, which is itself a fork of Spigot, which is a fork of vanilla server software distributed only as a Bukkit-API plugin platform. Forge and Fabric are not forks of that lineage; they are mod-loading frameworks that inject directly into vanilla’s own codebase, obfuscated Mojang mappings and all. There is no Forge or Fabric equivalent of Folia’s region-threading model, and this is not a resourcing gap that an eventual community mod will close. It is because a general-purpose region-threading rewrite has to touch the same tightly coupled AI, physics, and block-update logic that makes the vanilla tick loop hard to parallelize in the first place, and doing that safely across an ecosystem of hundreds of independently written mods (each with its own assumptions about what thread it runs on) is a substantially harder compatibility problem than doing it for a curated plugin API.
Mods like Async (Fabric) that claim to parallelize entity processing exist, but they operate at a narrower scope than Folia or ShreddedPaper, and mod authors and the community around them are explicit that these are experimental, can behave unpredictably, and are incompatible with a meaningful slice of the mod ecosystem. Treat them as a targeted experiment to test on a backed-up copy of your server, not a load-bearing fix for a production modpack.
What this means for diagnosing your own lag
If you administer a Forge or Fabric server and are chasing a multithreading fix because the tick loop feels slow, the architectural reality is that there isn’t one to reach for. Where the actual leverage is:
- Profile before guessing. A Spark profile shows you which category (entity ticking, chunk ticking, redstone, mob AI, pathfinding) is actually consuming the tick budget. “Single-threaded” is not a diagnosis; it’s the default state of the one thread you should be looking at. See our guide to reading a Spark profiler report if you’re not sure where to start.
- If the profile points at entity ticking or mob AI, the fix is spawn limits and activation range tuning, not more cores. Our Cobblemon/AllTheMons case study walks through exactly this pattern.
- If it points at chunk loading or world generation, that part is already threaded; the fix is pregeneration or lowering view/simulation distance, not multithreading it further.
- If it points at networking, check Netty thread count and packet-heavy plugins before assuming it’s tick-loop work at all.
- If you are on Paper (not Forge/Fabric) and specifically bottlenecked by many players spread across a large world, Folia is a real option, with the plugin compatibility cost that implies. ShreddedPaper is worth evaluating as an alternative with a different concurrency tradeoff, particularly if your plugin set already ported to Folia’s scheduler APIs.
The underlying pattern across all of these cases is the same: “multithreading” is not a single lever, it’s a description of several architecturally distinct pieces of the server, each with its own constraints. Knowing which piece is actually your bottleneck is what a profile is for.
Not sure which part of your tick is the actual bottleneck? Paste your Spark report into our analyzer for a free, instant breakdown of exactly where the time goes, no signup required.