architecture
how a document survives a crash
illustrative recovery trace- doc:a3f9 ops sequenced, clients attached
- sup doc:a3f9 exited: badarg
- sup doc:a3f9 restarted, state reloaded from storage
- doc:a3f9 client resumed at the same sequence number
- ok every other document session: untouched
Illustrative supervisor output, not a benchmark — one_for_one is the restart strategy Floodgate configures, and reloading from storage is what a restarted session does.
Each document session is its own BEAM process, supervised with a one_for_one restart strategy. If a session process crashes, it restarts and reloads its state from storage — the rest of the node, including every other document's session, is unaffected. The isolation comes from the runtime, not from Floodgate code; the sequencing and validation logic on top of it is written in Gleam, so a whole class of protocol bugs is caught by the compiler before the process ever starts.
the process tree
pstree floodgate
- floodgate
- socketio_transportofficial Fluid/Routerlicious wire format
- phx_transportPhoenix Channels wire format (levee-driver compatible)
- berylsupervised socket actors, channel routing, pubsub, presence
- document_channelauth, sequencing, signals, summaries
- storageper-tenant backend
- shelf (dets)default — persistent, one file per document
- etsin-memory, process-local
- memoryephemeral, used by tests
- spillwayprotocol: message types, sequencing, validation
Floodgate doesn't implement the Fluid protocol itself. It composes a handful of sibling Gleam libraries: some contribute workers to the process tree, while others provide protocol, cryptography, storage, and runtime utilities. Floodgate adds the transports, storage wiring, and admin surface around them.
composed from
- [lib] spillway — Fluid protocol: message types, sequencing, validation, signals, nacks
- [lib] beryl — supervised socket runtime, channel routing, pubsub, and presence
- [lib] signet — JWT signing and verification
- [lib] silt — Git object encoding and decoding
- [lib] windsock — Engine.IO and Socket.IO framing primitives
dual-mode, one process
socketio_transport and phx_transport are two wire-format adapters in front of the same beryl socket runtime, session state, and storage. A Fluid client on /socket.io/ and a Phoenix Channels client on /socket/websocket can collaborate on the same document at the same time; neither transport knows the other exists.
http surface (excerpt)
- GET
/health— readiness probe — {"status":"ok"} - POST
/documents/:tenant— create a document (id from body, or generated) - POST
/documents/:tenant/:id— create a document with an explicit id - GET
/documents/:tenant/:id/deltas— ops catch-up - GET
/repos/:tenant/git/refs— list refs - POST
/repos/:tenant/git/{blobs,trees,commits}— create a git object - GET
/api/tenants— list tenants (admin session or key)
full endpoint reference: HTTP surface
The fastest way to check any of this is to run it: the container builds from source and answers on /health in three steps.