Docs › Offload

Offloading terrain

Let other machines compute the heaviest step of terrain generation for your server, encrypted and with identical results.

Terrain generation happens in steps. The most expensive one, noise, decides the shape of the land: where there is stone, air, water and lava, caves and aquifers. It depends only on the seed, the world settings and nearby structures, not on neighboring chunks or on anything players did. That makes it possible to compute it on another machine.

With offloading, your Storia server (the client) sends noise requests to one or more workers. Each worker computes the noise and sends back the blocks. Everything else stays on the main server.

 Storia server (players, worlds)           Storia Worker (another machine)
   structures, features, light   --- request (chunk + nearby structures) --->
                                 <--- terrain blocks, heightmaps       ---   terrain noise

What moves and what stays#

Step Where
Structure starts and references Main server
Biomes Main server
Noise (terrain shape, caves, aquifers) Worker, if one is available
Surface, carvers, features (trees, ores), light, spawning Main server
Everything that ticks Main server

The steps after noise depend on neighboring chunks or must finish within a 50 ms tick, so they stay on the main server. The noise step is typically the largest single part of generation, so moving it frees a lot of CPU.

Identical results, always#

  • Probe on connect. When a server connects to a worker, both generate the same probe chunks for every dimension and compare hashes. A dimension is only offloaded if the results match exactly. A different seed, datapack or Storia build is refused for that dimension, and the log says why.
  • Validation. Every answer is checked before it is applied to the chunk.
  • Local fallback. If no worker has room, a worker is slow (timeout-ms) or disconnects, the chunk is simply generated locally. Players never wait on a broken worker.
  • Verification mode. Start the main server with -Dstoria.verifyOffload=true to also generate every offloaded chunk locally and compare. In our tests: 0 mismatches.

Setup#

You need:

  • the main Storia server,
  • one or more helper machines with Java 25, running the Storia Worker package,
  • optionally a Storia Relay, if you want workers to come and go without touching the server's config,
  • a shared secret of at least 8 characters.

Main server#

# storia.yml
offload:
  mode: client
  secret: "a long random secret"
  workers:
  - 192.168.0.20:25590
  - 192.168.0.21:25590

Restart. Offloading starts once the server has finished loading (Done).

Workers#

Follow Storia Worker. In short: unzip storia-worker-26.2.zip, copy the main server's world folder without its region, entities and poi folders, set the same secret, and run start-worker.sh.

With a relay#

Storia server --\                  /-- Worker A
                 >-- Storia Relay <---- Worker B
Storia server --/                  \-- Worker C

The server lists the relay as its only worker, and workers connect out to the relay. See Storia Relay.

Checking it works#

/storia offload
Client mode: 3120 chunks offloaded, 0 generated locally after a failure
 generated locally: 41 (workers busy), 0 (blending with old terrain), 0 (upgraded chunk), 12 (no plain noise state)
 192.168.0.20:25590: connected (encrypted), 6 threads, 7/24 in flight, 3120 done, 0 failed, avg 38.5 ms, dims [minecraft:overworld, minecraft:the_nether, minecraft:the_end]
Reason a chunk was generated locally Meaning
workers busy All connections were full. Add workers or threads.
blending with old terrain The chunk borders terrain from an older Minecraft version and needs blending.
upgraded chunk The chunk was partly generated by an older version.
no plain noise state Some chunks cannot be described to a worker. This is normal and rare.

Performance#

Pregenerating 3,721 chunks, main server on 3 cores, one worker on 3 other cores:

Time
Main server alone 1m 35s
Main server + 1 worker 1m 6s (95% of noise steps offloaded; 0 of 888 verified chunks differed)

The gain grows with more workers until the steps that stay on the main server become the limit. Offloading helps most with new terrain: exploration and pregeneration. It does not speed up entities or redstone.

Ports#

Every machine can use its own port. 25590 is only the default.

Machine Where the port is set
Worker (listening) offload.port in its storia.yml
Relay port= in relay.properties
Main server Nothing to open: it connects out. Each entry in offload.workers carries its own host:port.
Worker using a relay Nothing to open: offload.relay: "host:port" points at the relay's port.

For example, two workers on different ports:

# worker A (storia.yml)
offload:
  port: 10000
# worker B (storia.yml)
offload:
  port: 10001
# main server (storia.yml)
offload:
  mode: client
  workers:
  - 192.168.0.20:10000
  - 192.168.0.21:10001

Port forwarding works too: if your router forwards external port 10001 to a worker's 25590, list the external address and port (203.0.113.5:10001) on the main server.

Network#

  • Traffic uses one TCP connection per worker (or relay).
  • Traffic per chunk is small and compressed. A LAN or a VPN between data centers is ideal; high latency only makes each request slower, not the server.
  • Everything is encrypted and authenticated. See Encryption & security.