Many Worlds
A GreyCat server holds one graph: the main world. A server can also hold any number of other worlds. A world is a named branch of the graph. A task that runs in a world reads the graph as the world sees it and commits to the world only. Main never sees what the world writes.
main (the real system: live data)
│
┌────────────────┼────────────────┬──────────────────┐
│ │ │ │
scenario-a scenario-b scenario-c tenant-a
(overlay) (overlay) (snapshot) (standalone)
writes the writes another frozen copy of its own graph,
predicted future main at t0 nothing shared
future
Worlds share the storage of the server. A world shares every block it has in common with its base, so a world costs only what it writes. An overlay world is created instantly, whatever the size of the graph. One server can run a hundred worlds side by side, with the same workers, the same memory budget and the same API.
What worlds are for
Namespaces. Several graphs run concurrently in one server. Each stakeholder, customer or team works in its own world, isolated from the others, while the server, its workers and its storage are shared. See Namespaces.
Simulation. This is what worlds were mostly designed for. A world is a change scenario: it holds alternative values for many nodes, and above all new points in nodeTime series, the predicted future of the system. You run your functions inside the world to compute a conditional future: what happens if the vessel sails at 8 knots instead of 11? See Simulation.
Sharing results. A world outlives the task that filled it. You keep it, give other users access to it, and they call your API in that world to read the scenario as if it were real. See Namespaces.
Search. Worlds can be the base of a search engine. An algorithm, a genetic algorithm for instance, forks one world per candidate, evaluates them all in parallel, keeps the worlds on the Pareto front and removes the others. See Scenario Search.
Whatever the use, one question always comes back: what did this world change? GreyCat answers it natively with WorldChangesReader and WorldDiffReader, which list the changes of a world against its base, node by node and key by key. See World Diff.
The pages of this section
| Page | What it covers |
|---|---|
| Basics | The World API, the three modes, how to run code in a world, limits |
| Namespaces | Isolating stakeholders, the worlds a user may use, sharing a world |
| Simulation | Writing a predicted future in a world and evaluating it |
| World Diff | Listing what a world changed, comparing scenarios, drift against reality |
| Scenario Search | Parallel evaluation of many worlds, genetic search, Pareto front |
The running example
The pages of this section share one small model, a fishing vessel whose speed and fuel consumption are time series:
type Vessel {
name: String;
/// knots
speed: nodeTime<float>;
/// litres per hour
fuel_rate: nodeTime<float>;
config: node<EngineConfig>;
}
type EngineConfig {
mode: String;
max_rpm: int;
}
var vessels: nodeIndex<String, Vessel>;
fn seed() {
var start = time::parse("2026-10-26T06:00:00Z", null);
var v = Vessel {
name: "trawler",
speed: nodeTime<float> {},
fuel_rate: nodeTime<float> {},
config: node<EngineConfig> { EngineConfig { mode: "diesel", max_rpm: 1500 } },
};
for (var h = 0; h < 6; h++) {
v.speed.setAt(start + h * 1hour, 10.0);
v.fuel_rate.setAt(start + h * 1hour, 300.0);
}
vessels.set(v.name, v);
}
Main holds what really happened: six hours of measurements, from 06:00 to 11:00. The worlds hold what could happen next.
World,WorldChangesReaderandWorldDiffReaderare in theruntimemodule ofstd.