Skip to content

Slices and scale

One line carries a wisp in any number of servers: it follows one group and keeps one cursor, whether the wisp is in 3 servers or 5,000. Most wisps never need more. Slices are for the wisp that one process can no longer keep up with.

Split when one process cannot handle what its line hears: a wisp that reads every line of many busy servers, or one whose work per event is heavy. Each slice is its own line, usually its own process, hearing only the servers in that slice. One slice is the default, and costs nothing to keep.

Set the number when you make the wisp, or change it later:

PATCH /api/wisps/d2b6f4a8-3e1c-4b7d-9a05-6c8e0f2a4b19
Authorization: Bearer <your token>
Content-Type: application/json
{ "slices": 4 }

From 1 to 64. A change counts at once: from then on, each server’s events go to its slice under the new number. Lines already open stay open and keep their slice, and their ready still names the old number. So open a line for each new slice, close any line whose slice is past the new number, and since servers moved between slices, catch each slice up with reads on the line (The line). Every line counts against the cap (below), so going down, close the extra lines first.

The first eight hex digits of the server’s id, read as a number, mod the number of slices. Work it out like this:

function sliceOf(server, slices) {
return Number.parseInt(server.slice(0, 8), 16) % slices;
}
sliceOf("5c3b1a2d-8e4f-4a6b-9c7d-0e1f2a3b4c55", 4); // 0x5c3b1a2d is 1547377197: slice 1
sliceOf("5c3b1a2d-8e4f-4a6b-9c7d-0e1f2a3b4c55", 8); // slice 5

Each line names its slice in its hello:

{"t":"hello","v":2,"a":"eyJhbGciOiJIUzI1NiJ9.eyJuYW1laWQiOiJkMmI2ZjRhOCIsIndpc3AiOiIxIn0.c2ln","f":1,"slice":3}

Left out, it is slice 0. A slice that is not one of your wisp’s (3 when it has 2) is closed with 1011. Everything about a server, its command and act events and its server grants included, arrives on that server’s slice. Make the calls about a server from the same line, so your own order of calls for a channel holds.

The budgets are your wisp’s, not a slice’s: serverCalls, channelLines and edits are shared by all its lines, while each line has its own calls (Budgets and limits).

A wisp may hold two lines for each slice: at most twice as many lines as it has slices, counted across the whole wisp. One past that is closed with 4429, retry=30. The second line is for hand-overs: while both are open, both hear the slice’s group, and at the new one’s ready the old one says moved and goes.

Woosh deploys itself without anyone going offline, and your wisp can too:

  1. Start the new version beside the old one.
  2. For each slice, the new process opens a line with the cursor the old one saved.
  3. At each new line’s ready, the old process sends moved on its line for that slice, finishes the answers it owes, and lets go.
  4. Once every slice has moved, stop the old process.

Nothing is missed and nothing is answered twice: Woosh never lets a run take two answers. Decide which process answers during the overlap (the new one, from its ready), so the two do not race for each run.

Shape What it costs your wisp
A wisp in 5,000 servers one group, one cursor and one line per slice
A busy server’s lines one event each
A command or a press one event in, one answer out
A tally pressed 5,000 times nothing: Woosh counts it
A countdown, pages, an animation nothing after the card is sent

Your wisp pays its own distance twice for every command: once hearing it, once answering. Run it close to Woosh, and answer from memory rather than a slow database call where you can.

© 2026 Woosh AS. All rights reserved.