momo originally assumed that blob bytes and blob metadata lived on the same machine, in the same local directory. That assumption was fine until the project grew an S3-compatible gateway and remote replication. At that point the placement of bytes had to diverge from the node holding the metadata — and we did not want that divergence to require rewriting the storage core.

The storage layer therefore exposes one interface and a single configuration switch. A backend is simply the thing that stores and retrieves opaque blob bytes. A seam is a narrow, compile-time interface we can substitute without a plugin runtime: no shared library, no RPC hop, no serialization boundary.

The Store interface stays stable, and a [storage] backend config value chooses the implementation:

BackendNotes
localfilesystem path, default
nfsshared filesystem volume
s3remote object store over SigV4, TLS-gated (see 011)
rawblock-device direct I/O

Local metadata stays per-node; only the blob bytes route through the chosen backend.

Pluggable storage backends architecture
Pluggable storage backends architecture

The seam, not the plugin

Backends are compiled in and selected by declarative config — the embryo of the project’s seam-over-plugins principle. There is no external .so to load and no RPC plugin protocol to negotiate. The blob interface is small and stable (PutBlob/GetBlob/DeleteBlob/stat/path), and each backend implements it with its own guarantees. That keeps the trust boundary explicit and the binary self-contained.

The trap this avoids

A single hard-coded local blob store was the original design. Once remote replication arrived, “metadata here, bytes there” had to become a configuration change rather than a rewrite. Pluggable backends are what made that possible: the CAS core keeps naming blobs by hash and recording metadata locally, while the bytes can live on NFS, in an S3 bucket, or on a raw block device.

⚡ Bolt lens

  • The GetBlobPath guard rejects non-local backends, because “a filesystem path” is a concept only the local backend can honor.
  • Combined metadata reads collapse three separate key/value views into one, cutting write-path transactions and CPU (perf work referenced in 024).
  • The encryption layer later wrapped the store so end-to-end encryption could sit under the backend seam transparently (013) — a seam earning its keep.

See docs/CORE/STANDARDS.md for the ⚡ Bolt / 🛡 Sentinel mindsets.

References / Dig deeper