File infrastructure for modern applications

Build file features. Keep the storage boundary changeable.

When your product needs paths, handles, directories, and sync semantics, mount-rs gives you a stable Rust and Node contract for direct access—or a real mounted filesystem through FUSE, NFS, 9P, or FSKit. HTTP and WebDAV provide network edges when a mount is not the right fit, while namespace metadata and immutable blocks stay explicit and replaceable.

Open source · Apache-2.0 · prerelease · evidence-led

one contract / explicit choices

01Your applicationreads · writes · file semantics
02mount-rs contractRust core · Node bindings · mountable edges
03AMetadatanamespace · revisions · leases
03BImmutable blockschunks · bytes · barriers

The problem

File features turn infrastructure assumptions into product risk.

A mount can work on one laptop and still be the wrong boundary for a container, serverless process, desktop app, or Node service. The hard part is not reading a file. It is keeping namespace, bytes, lifecycles, and deployment choices coherent.

01 / deployment

Mounts are a runtime dependency.

FUSE, NFS, FSKit, permissions, daemons, and platform-specific setup become part of the application you are trying to ship.

02 / correctness

Metadata and bytes do different jobs.

Namespace and revisions need publication and fencing. Object or block storage needs immutable bytes and durable barriers. Mixing the two makes failure behavior difficult to reason about.

03 / change

Infrastructure choices become API choices.

Switching from local files to SQLite, a database service, or an object store should not require rewriting every file operation in the product.

The mount-rs answer

One observable file contract. Three decisions you can change independently.

mount-rs keeps the core small and makes the boundary visible: use the API directly, create a real mount for a host, or put HTTP/WebDAV at the edge. Choose where namespace metadata lives and where immutable blocks are stored independently.

01

Contract

Use paths, handles, stats, directory operations, and explicit sync behavior from Rust or Node.

Explore the core API
02

Storage planes

Compose a metadata provider with an immutable block provider, then flush blocks before publishing references.

Compare providers
03

Mounts and transports

Create a real filesystem mount with FUSE, NFS, 9P, or FSKit where the platform integration is available; use HTTP or WebDAV when the edge is networked.

Choose the edge

The storage model

See what happens to one file.

The same file operation crosses a namespace plane and an immutable block plane. This conceptual view makes the ordering visible without pretending every provider uses the same physical schema.

Illustrative provider view

/reports/q3.pdf
schemas vary by provider
Conceptual file record
namespace:
  path: /reports/q3.pdf
  revision: 7
  size_bytes: 131072
  blocks: [block_01, block_02]

block_01:
  key: files/7/block_01
  bytes: 65536
  immutable: true

Metadata carries inode attributes, directory entries, and block references. It does not carry the file bytes.

  1. 01

    Namespace / metadata

    Describe the file before publishing it.

    Keep inode attributes, directory entries, and block references in the metadata contract. The namespace points to bytes; it does not become the byte store.

  2. 02

    Immutable blocks

    Write fixed-size chunks and finish the block barrier.

    Chunk the file according to its layout, write immutable blocks, and wait for the block-store barrier before metadata can refer to them.

  3. 03

    Publish

    Commit the reference with a fence.

    Publish with revision CAS and a monotonic writer fence, then complete the metadata barrier before the write is acknowledged.

Operational boundary: ownership loss fails closed. An uncertain commit can leave unreferenced blocks; automatic GC and copy-on-write are not implemented yet.

How to use it

Start local. Keep the boundary when the deployment changes.

Begin with a direct loopback contract, choose the storage planes your workload needs, then either create a real mount for the host or expose a network transport. The application contract stays the same while the edge changes.

01

Define the file contract

Give your application file operations without requiring a kernel mount.

02

Select the planes

Keep namespace and immutable bytes explicit so each provider has one job.

03

Mount or transport it

Create a real mount through FUSE, NFS, 9P, or FSKit when the host needs a filesystem; choose HTTP or WebDAV for a network edge.

Rust / direct contract
let fs = Loopback::new(MemoryFs::new(MemoryOptions::default()));
fs.write_file("/hello", b"hello").await?;
let bytes = fs.read_file("/hello").await?;
Node / split-store factory
const fs = await createChunkedDriver({
  metadata: { kind: 'sqlite', uri: './metadata.sqlite' },
  blocks: { kind: 'sqlite', uri: './blocks.sqlite' },
  chunkSize: 65536,
});
await fs.writeFile('/hello', Buffer.from('hello'));

Choose the boundary

Use the storage model that fits the workload.

mount-rs is a choice for teams that want file semantics without making a platform mount or one storage service the product API. It is not the right abstraction for every workload.

Choose mount-rs when

Your product needs files, but infrastructure still needs to move.

  • Paths, handles, directory operations, and sync semantics belong in the product.
  • Metadata and immutable blocks need separate operational roles.
  • Rust, Node, and edge transports should share one contract.
Read the adoption guide
Use direct object APIs when

The application is object-native.

If callers already work in buckets, keys, immutable objects, and provider-native lifecycle rules, adding filesystem semantics may create more surface area than it removes.

Review the storage roles
Use a real mount when

Existing tools expect a mounted path.

FUSE, NFS, 9P, and FSKit put the filesystem surface back into a host when users or existing software expect a mounted path. Platform permissions, daemon lifecycle, and qualification remain part of that choice.

Compare transports

What changes for your team

Infrastructure can move without rewriting the product boundary.

Ship soonerUse memory or local providers while the product takes shape.
Change deliberatelyMove metadata, blocks, or edge transport as separate decisions.
Explain the riskRead provider maturity and acceptance evidence before production claims.

Proof, not promises

Know what is usable now—and what still needs qualification.

mount-rs is a prerelease project. The docs separate repository implementation, local tests, and live provider evidence so you can make an informed adoption decision.

✓

In the tree

  • Core Rust FsDriver and FileHandle contracts.
  • Independent metadata and immutable block provider APIs.
  • Rust and Node entry points plus transport integrations.
→

Still being qualified

  • Windows runtime qualification and revision-matched platform CI.
  • Durability, failure recovery, broader provider lanes, and native mount gates.
  • Production operations, release coverage, and deployment-specific guarantees.

Make the boundary explicit

Build the file feature. Keep your infrastructure options open.