Parallel tick processing for Minecraft servers, built on Paper.
Mica adds transparent multi-threaded tick execution to the Minecraft server using a Snapshot-Compute-Merge-Converge (SCMC) architecture. Unlike Folia, which splits the world into independent regions that cannot interact, Mica maintains a single unified world where all game systems can read the same global state. Parallelism comes from snapshot isolation, not spatial partitioning.
Status: Experimental. Random ticks, entity ticks, and scheduled block/fluid ticks are parallelized. Redstone circuits work correctly with all three Paper evaluators (Vanilla, Eigencraft, Alternate Current). Not ready for production use.
Every Minecraft server tick (50ms), the server processes block updates, entity AI, mob spawning, crop growth, redstone, fluid flow, and more, all on a single thread. Mica changes this:
-
Snapshot - At tick start, capture an immutable view of the world state. This is O(1) using copy-on-write references to chunk section arrays - no deep copy.
-
Compute - Dispatch tick operations across a thread pool. Each worker thread gets a tracked overlay - a read-write layer on top of the snapshot. Game code calls
level.getBlockState()andlevel.setBlock()as usual, but these calls are transparently redirected to the overlay via thread-local interception. Reads check the overlay first, then fall through to the snapshot. Writes go into the overlay only. -
Merge - Collect all overlays. Most writes don't conflict (different positions). For conflicts, walk the provenance graph to identify exactly which operations are affected, and re-run only those operations serially.
-
Apply - Commit merged writes to the live world. Replay deferred side effects (entity spawns, Bukkit events) on the main thread.
Folia splits the world into spatial regions that tick independently. This works well for spread-out players but has tradeoffs:
- Redstone, entities, and hoppers can't cross region boundaries without async scheduling
- Every plugin must be rewritten for region-aware execution
- Players in the same area share a single region (no parallelism benefit)
Mica takes a different approach: all workers see the same global snapshot, so there are no boundaries. A redstone wire can span any distance. A hopper can pull from any chest. Plugins call level.getBlockState() and get a consistent answer regardless of which thread they're on. Conflicts are rare and handled automatically by the merge phase.
When two workers' overlays conflict (writing to the same position, or one reading a position the other wrote), Mica doesn't throw away all work. Each overlay tracks which operation caused each read and write. The merge phase walks this provenance graph to find exactly the affected operations, discards only their results, and re-runs them serially. Everything else keeps its parallel results.
For cascading systems like redstone, Mica also tracks "touched positions", positions read during a neighbor update cascade triggered by a write. Even if the value didn't change, the position was causally influenced. If another thread read that position, a conflict is detected.
After conflict detection, Mica groups ticks into independent connected components using Union-Find. Only tainted components are re-run. Clean components keep their parallel results. When multiple tainted components exist (e.g., 20 separate water pools flowing during chunk generation), they are re-run in parallel with each other, each group gets its own overlay and runs on a worker thread. This means even worst-case scenarios with many conflicts can still benefit from parallelism. Two independent redstone machines, or 20 separate lava flows, all execute concurrently.
In practice, conflicts are rare for random ticks and entity ticks. Empirical data from live testing shows random ticks have a conflict rate of effectively 0% even under extreme stress (100,000x tick speed, 9.5 million reads per interval). Scheduled ticks with interacting redstone circuits produce conflicts that are detected and resolved automatically.
- Random block ticks (crop growth, ice/snow formation, fire spread, leaf decay, etc.) - dispatched across a configurable thread pool with per-thread overlays
- Entity ticking (AI, pathfinding, movement, collision) - 5,000+ villagers at 34ms on 8 threads with entity position snapshots for cross-entity read safety
- Scheduled block ticks (redstone repeaters, comparators, gravity blocks) - with cascade conflict detection and independent tick grouping via Union-Find
- Scheduled fluid ticks (water and lava flow)
- Entity spawns during parallel ticks (e.g., item drops from leaf decay) are buffered and applied on the main thread after the parallel phase
- Bukkit events that require the main thread (BlockSpreadEvent, BlockGrowEvent, etc.) are buffered and replayed
- Entity chunk moves during parallel entity ticks are deferred to prevent concurrent modification of chunk entity lists
- Block entity creation/removal during parallel block ticks
- Scheduled ticks (scheduleTick calls during parallel phase) - tagged with source operation, replayed per-group after merge
- Block entity ticking (hoppers, furnaces)
- Block events (pistons)
net.minecraft.server.level.mica/
├── WorldSnapshot.java # Immutable world view at tick start (COW chunk sections)
├── TrackedOverlay.java # Per-thread read-write layer with provenance tracking
├── OperationId.java # Unique identifier for each tick operation
├── OperationType.java # Enum of operation types (block tick, entity tick, etc.)
├── OverlayMerger.java # Pre-indexed conflict detection via provenance graph walking
├── TickGrouper.java # Union-Find grouping of independent tick components + parallel re-run
├── MicaTickEngine.java # SCMC cycle orchestrator
├── TickOperation.java # Operation wrappers (BlockTickOp, EntityTickOp, etc.)
├── OperationExecutor.java # Functional interface for executing operations
└── DeferredEffects.java # Buffers entity spawns, events, scheduled ticks for main thread replay
Key integration points in the server:
LevelChunk.java- Overlay intercept at chunk level (transparent to game logic above)Level.java- Thread-local intercepts ongetBlockState(),getFluidState(); suppresses packets/rendering innotifyAndUpdatePhysics()during parallel phaseEntity.java- Position/bounding box snapshots for cross-entity read safetyServerChunkCache.java- Parallel dispatch initerateTickingChunksFaster(); thread pool and loggerServerLevel.java- Entity tick parallelism, scheduled tick parallelism (micaRunScheduledTicks)LevelTicks.java-collectForParallelDispatch()/finishParallelDispatch()for tick collectionEntityLookup.java- Entity chunk movement and removal deferral during parallel phaseOverlayMerger.java- Pre-indexed position→reader and operation→position maps for O(1) conflict detectionLevelHelper.java- Alternate Current wire state overlay interceptRedStoneWireBlock.java- ThreadLocalshouldSignalfor vanilla redstone evaluator safetyPaperEventManager.java- Sync event deferral during parallel executionAsyncCatcher.java/TickThread.java- Worker thread bypass during parallel execution
| Paper | Folia | Mica | |
|---|---|---|---|
| Threading model | Single-threaded tick | Regionized parallel | Snapshot-isolated parallel |
| World model | One world, one thread | Independent regions | One world, parallel reads |
| Plugin compatibility | Full | Requires rewrite | Mostly compatible* |
| Cross-region interaction | N/A | Async scheduling required | Transparent (snapshot) |
| Redstone correctness | Full | Per-region only | Full (conflict detection + serial fallback) |
| Entity scaling | ~200 villagers/tick | Per-region | 5,000+ villagers on 8 threads |
| Conflict handling | N/A | Forbidden | Automatic (provenance graph + Union-Find grouping) |
*Cancellable Bukkit events during parallel execution are currently deferred - see HARDENING.md
- Core SCMC infrastructure (snapshot, overlay, merge, provenance tracking)
- Thread-local world access interception
- Parallel random chunk ticks
- Deferred entity spawns and Bukkit events
- Parallel entity ticking with position snapshots
- Parallel scheduled block and fluid ticks
- Cascade conflict detection (touched positions)
- Independent tick grouping (Union-Find connected components)
- Per-thread Alternate Current WireHandler
- Vanilla/Eigencraft redstone evaluator safety (ThreadLocal shouldSignal)
- Transparent overlay at LevelChunk level (vanilla game logic runs naturally)
- Full conflict detection with provenance graph walking
- Parallel re-run of independent tainted groups
- Pre-indexed merge and grouper (sub-millisecond with thousands of ticks)
- Entity removal deferral for chunk unload safety
- willTickThisTick correctness (markTickExecuted matching vanilla behavior)
- 10-player multiplayer stress test
- 4-bit adder timing verification
- Parallel block entity ticking (hoppers, furnaces)
- Buffered block update packets to eliminate flicker
- Cancellable Bukkit event support during parallel execution
- Configurable thread count and subsystem opt-in
- Performance benchmarking vs Paper and Folia
- Plugin compatibility testing
Mica draws on well-established concepts from several fields:
- Software Transactional Memory (STM) - Workers execute optimistically, conflicts are detected at commit time and resolved by retry. No locks, no deadlocks.
- Snapshot Isolation (databases) - Readers see a frozen point-in-time view. Our provenance graph walking implements serializable snapshot isolation (SSI) to detect and fix anomalies.
- Domain Decomposition (scientific computing) - Folia's approach. We chose task-based parallelism over spatial decomposition, but the boundary/halo concepts informed our design.
- Entity Component Systems (game engines) - Systems declare read/write access, scheduler parallelizes non-overlapping systems. Our overlay tracking achieves the same result dynamically at runtime.
Download or build the Mica jar and run it just like a Paper server.
Mica logs parallel tick stats every 200 ticks:
[Mica] 8 threads | 441 chunks | 98700246 reads, 80 writes | 0 conflicts, 0 tainted, 0 re-runs
[Mica] Timing: 36.38ms total | snapshot 0.04ms | compute 36.14ms | merge 0.02ms | converge 0.00ms | apply 0.18ms
[Mica] [Entities] 34.12ms | 8 threads | 5104 entities | 133583 reads, 0 writes, 0 deferred
[Mica] [Mica/Scheduled] 4 groups (3 clean, 1 tainted) from 5 ticks
- Paper documentation applies to Mica: docs.papermc.io
Mica is API-compatible with Paper. Existing Paper plugins should work without modification in most cases. See HARDENING.md for known edge cases around event timing during parallel ticks.
- See the Paper API here
- Paper API javadocs: papermc.io/javadocs
<repository>
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository><dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.21.11-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>repositories {
maven {
url = uri("https://repo.papermc.io/repository/maven-public/")
}
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT")
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
}Requires JDK 21 and an internet connection.
git clone https://github.com/oberhauserg/Mica.git
cd Mica
./gradlew applyPatches
./gradlew createMojmapBundlerJarThe server jar will be in paper-server/build/libs/.
To get a full list of tasks, run ./gradlew tasks.
See Contributing and HARDENING.md for current priorities.
For branches of Paper versions 1.8-1.21.3, please see Paper's archive repository.
Inherits Paper's license. See LICENSE.md.
Built on PaperMC and the work of the Paper team, especially Spottedleaf's chunk system and Starlight lighting engine.