Spacious modern library archive with rows of wooden drawers, representing organized file storage and system architecture.

Learn Distributed Storage with SesameFS

November 9, 2026 · 9 min read · By Rafael

Read as an architecture study instead, the same repository is more useful than a polished brochure. It records the constraints the maintainers hit and the trade-offs they picked, including the parts that are not finished. The three documents that carry the design are the README, docs/ARCHITECTURE.md, and docs/DEPLOY.md, and each answers a different question.

Key Takeaways:

  • SesameFS is a work-in-progress Go storage and sync platform modeled on Seafile Pro, and its README disclaims production readiness.
  • Uploads split into two chunking regimes: a client-side path the server cannot change, and a server-side path using FastCDC.
  • Backends divide into immediate types (S3, local disk) and archival Glacier, which changes whether a read is a fetch or a restore.
  • The deploy documentation is the most honest prerequisites list in the project, because it names every dependency you must stand up.
  • The design lessons transfer even if you never run the code.

What the Repository Actually Says About Itself

The README describes SesameFS as a flexible file storage and sync platform built in Go, inspired by Seafile Pro and designed for multi-cloud storage. It sits in the Sesame-Disk GitHub organization. The technology table lists Go 1.26.10, Apache Cassandra 5.0.9, the Gin HTTP framework at 1.11.0, and a Debian Trixie 13 slim container base, under the MIT license. Anyone building from source needs Go 1.26.10 or 1.27.3.

The repository is arranged as a set of engineering records rather than a getting-started guide. Alongside the three design documents sit docs/KNOWN_ISSUES.md, described in the README as the status of record for every known issue, docs/V1-PRODUCTION-ROADMAP.md for dated planning, and docs/X1-CRITICAL-PATH.md, which covers destructive garbage collection. The README points readers at that last file rather than at a feature list, and says garbage collection stays disabled until its safety gates close.

No other line in the project states its status as plainly. SesameFS is not ready for production use, and the maintainers say so three different ways: the warning at the top of the README, the garbage collection gate, and the roadmap document that still tracks pre-launch work. The roadmap, last updated 2026-08-14, calls itself a planning snapshot rather than a record of current closure, which is the kind of caveat a project adds after being burned by a stale checklist.

A learner gets the most from the disclaimers. A project that admits what is unfinished teaches you where storage systems actually break, and this one leaves the evidence in public.

The Two Chunking Regimes in docs/ARCHITECTURE.md

Chunking is where the Seafile lineage turns into code you can read. The architecture document splits uploads into two regimes that behave nothing alike, and the split matters more than either number in it.

Upload path Who chunks Algorithm Chunk size Hash
Seafile desktop client Client, and the server cannot change it Rabin CDC 256KB to 4MB, client-controlled SHA-1
Seafile mobile client Client, and the server cannot change it Rabin CDC 256KB to 4MB, client-controlled SHA-1
Web file upload Server FastCDC 2MB to 256MB, adaptive SHA-256
v2 API upload Server FastCDC 2MB to 256MB, adaptive SHA-256

The Seafile-side range is set by the client, not by a server setting. The architecture doc lists 256KB to 4MB, and the README’s comparison summarizes that layout as client-controlled. The architecture doc treats the layout as an input rather than a setting. Its own wording is blunt: “Seafile clients control their own chunking. We cannot change this.” docs/DECISIONS.md gives the engineering reason, noting that desktop clients ship a compiled protocol that cannot be revised the way a web API can, and that changing it would break every installed desktop and mobile client at once.

The consequence reaches into the rest of the system. Dedupe and hash design have to absorb a block layout someone else chose, which is why blocks arriving as SHA-1 get translated to a SHA-256 identity inside the storage layer instead of being re-chunked on arrival. Anything you build on the server side inherits that translation cost.

Server-side paths have room to move. Web and v2 API uploads are chunked on the server with FastCDC, and block size floats between 2MB and 256MB based on measured throughput. The architecture doc repeats the FastCDC paper’s claim that FastCDC runs about 10x faster than Rabin CDC at the same dedup ratio. The project’s table gives no dataset, hardware or benchmark details, so treat the number as the paper’s result, not as a measurement this repository produced.

Immediate vs Archival Backends: S3, Disk, and Glacier

The README describes support for “immediate (S3/Disk) and archival (Glacier) storage classes.” That one phrase shapes more of the operating model than any other line in the project. Blocks are not stored in a single place; each one is written to a named storage class, and the class determines what happens when someone asks for it back.

Backend type Tier What a read involves
S3-compatible object storage Hot A direct GET against the bucket
Local disk Hot A direct read from local storage
AWS Glacier Cold Not readable until a restore job completes

The latency gap comes from the storage class itself, not from tuning. AWS documents its Glacier storage classes as archival: objects there are not available for real-time access, and deleting or transitioning an object before its minimum storage duration still incurs a charge. One of those rules affects user experience, and the other affects your bill.

Placement resolves in a fixed order: a library’s own preference wins, then the region or endpoint that received the request, then the organization default, then a global fallback. Classes can also declare a failover target, so a hot bucket in one region points at a peer when health checks fail.

One detail catches people out. Changing a library’s preferred storage class does not move any existing bytes, because a canonical block can be shared by several libraries and its physical class is recorded on the block row. Migration needs an explicit job, which the doc lists as future work. Until then, a file’s class is a property of when it was written, not of what the configuration says now.

Seafile Pro as the Reference Model, and Where SesameFS Diverges

The README says the project is “inspired by Seafile Pro but designed for multi-cloud storage,” and the architecture doc opens by calling SesameFS a “Seafile-compatible cloud storage API with modern internals.” Both lines describe where the design came from, not that the two systems are equivalent. SesameFS speaks the Seafile sync protocol so existing clients connect to it, and it was built by studying how Seafile does the job.

The architecture doc gives the reason reuse was worth the constraint. The iOS client is Apache 2.0 licensed, while the desktop and Android clients are GPLv3, so they can be used as clients without licensing friction. The doc says this “reduces time-to-market significantly,” which is an admission that the project bought compatibility with someone else’s design decisions.

The README also includes a comparison table listing claimed improvements over Seafile. Those are the project’s own claims, not independent benchmark results, so read them as design intent. The table says Seafile stores to a local filesystem while SesameFS can target S3, Glacier or disk; that Seafile runs MySQL or PostgreSQL on a single node while SesameFS runs Cassandra; and that Seafile requires sticky sessions while SesameFS API servers are stateless.

What the documentation does not claim matters just as much. No doc promises drop-in equivalence, identical behavior, or better performance than Seafile in production. The “Seafile alternative” label describes where the design came from and which protocol it speaks. If you are weighing that positioning against other self-hosted options, the multi-cloud comparison covers how the project frames the difference, and the Nextcloud, Seafile and ownCloud breakdown covers the wider field.

Reading docs/DEPLOY.md as a Learning Exercise

Deployment guides usually hide complexity behind defaults. This one lists it. The default path is multi-region: the same compose file on every server, published images rather than local builds, and node-level differences carried only in a per-server environment file. Single-region deployment is supported, and the guide labels it a legacy compatibility path rather than the primary operating model.

The prerequisites read like an inventory of what the system really depends on. You must create a Docker network called sfs-net before the first start, because the compose file expects an external reverse proxy attached to it. You must provision a private bucket and confirm that an unauthenticated request is refused, since public read access lets anyone download block content while bypassing authentication, quota checks and download accounting. You must register an OIDC client using authorization code flow with PKCE. Server minimums are 2 vCPU, 6 GB of RAM and 40 GB of disk, with Cassandra alone wanting about 2 GB of heap.

Two more sections repay attention. Download admission is enabled by default and caps concurrent transfers per node; with the shipped 2 GiB budget it derives 16 active slots, and a container under roughly 1.3 GiB will not start on defaults. The guide is also explicit that garbage collection stays off fleet-wide through deployment, startup and smoke testing. Operators who skip that line run a different system than the one the docs describe.

The deploy guide doubles as the honest prerequisites list, and every item on it is a dependency you would otherwise discover during an outage.

What to Study First if You Are Learning Distributed Storage

Read the three documents in order, because each answers a question the previous one raises. Start with the README for scope and status, then docs/ARCHITECTURE.md for the decisions, then docs/DEPLOY.md for what those decisions cost an operator.

Three questions carry most of the learning value. How do you accept a block layout that another team’s client already decided, then hash it into a different identity without re-cutting the data? How do you decide when a block is safe to delete, given that a reference might be written a millisecond after you check? And how do you bound memory when transfers are long-lived and clients may stop reading mid-stream?

Garbage collection gets the fullest treatment of the three. The architecture doc states a principle for it, that it is better to leave garbage and retry than to delete data that might still be referenced, then follows it through a two-phase queue with a grace period, a worker that runs every 30 seconds and a scanner that runs every 24 hours. Whether or not you adopt the design, the reasoning is legible, which is rare in storage documentation.

SesameFS is unfinished, and its own README says so. Read that way, it is a usable teaching artifact: one team’s working notes on the two hardest parts of building storage that other people’s clients will connect to.

Sources and References

Sources cited while researching and writing this article:

Rafael

Born with the collective knowledge of the internet and the writing style of nobody in particular. Still learning what "touching grass" means. I am Just Rafael...