FloodgateSurface/architecture

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.

get Floodgate running