# How SQLiteWorkspaceProvider Bridges Durable Object Storage to FUSE Mount Operations

> Discover how the SQLiteWorkspaceProvider adapter connects Durable Object storage to FUSE mount operations. Translate filesystem calls into SQLite queries for cloud-persistent storage.

- Repository: [Cloudflare/computer](https://github.com/cloudflare/computer)
- Tags: internals
- Published: 2026-08-14

---

**The `SQLiteWorkspaceProvider` adapter translates `@platformatic/vfs` filesystem calls into SQLite queries on a Durable Object-backed database, enabling FUSE mounts of cloud-persistent storage.**

The `SQLiteWorkspaceProvider` is the core architectural component in Cloudflare's `computer` repository that turns a Durable Object (DO)-backed SQLite database into a fully functional virtual filesystem. By implementing the **@platformatic/vfs** `VirtualProvider` interface, this adapter allows POSIX-like filesystem operations to persist in SQLite while exposing them through a FUSE mount point on the local machine.

## Architecture Overview

The bridge consists of five coordinated layers that transform high-level filesystem calls into low-level SQLite operations:

| Layer | Responsibility | Implementation Location |
|-------|---------------|------------------------|
| **Durable Object storage** | Persists content-addressed blobs in SQLite tables | [`packages/dofs/src/testing.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/testing.ts) (`SQLiteTestStorage`) |
| **SQLiteWorkspaceProvider** | Implements `VirtualProvider` interface using DO storage | [`packages/dofs/src/provider.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/provider.ts) |
| **Prototype splice** | Injects `VirtualProvider` inheritance at runtime only in `computerd` | [`packages/computerd/src/fuse/vfs.ts`](https://github.com/cloudflare/computer/blob/main/packages/computerd/src/fuse/vfs.ts) |
| **NodeVirtualFileSystem** | Creates VFS instance with `dofs`-specific method extensions | [`packages/computerd/src/fuse/vfs.ts`](https://github.com/cloudflare/computer/blob/main/packages/computerd/src/fuse/vfs.ts) |
| **FUSE driver** | Mounts the VFS and translates kernel calls to provider methods | [`packages/computerd/src/fuse/driver.ts`](https://github.com/cloudflare/computer/blob/main/packages/computerd/src/fuse/driver.ts) |

```

Durable Object (SQLiteTestStorage) → Database
      ↓
SQLiteWorkspaceProvider (implements VirtualProvider)
      ↓  (prototype splice)
NodeVirtualFileSystem (via @platformatic/vfs.create)
      ↓
FUSE driver (computerd) → mount point

```

## How the Adapter Works

### Provider Construction and Prototype Splicing

The `createNodeVirtualFileSystem()` function in [`packages/computerd/src/fuse/vfs.ts`](https://github.com/cloudflare/computer/blob/main/packages/computerd/src/fuse/vfs.ts) handles initialization. A critical implementation detail is the **prototype splice**—necessary because `SQLiteWorkspaceProvider` cannot statically depend on `@platformatic/vfs` (it targets Workers environments).

```typescript
// packages/computerd/src/fuse/vfs.ts
export async function createNodeVirtualFileSystem(
  options: CreateOptions = {},
): Promise<NodeVfsHandle> {
  ensureVirtualProviderPrototype();                     // ← splice prototype
  const storage = new SQLiteTestStorage();              // DO-backed SQLite
  const db = new Database(storage);
  initializeSchema(db, () => Date.now());

  const provider = new SQLiteWorkspaceProvider(db);     // ← core adapter
  const vfs = create(provider as unknown as VirtualProvider, { moduleHooks: false });
  // expose extra dofs methods on the VFS instance …
  return { vfs, db, stopSync };
}

```

The `ensureVirtualProviderPrototype()` function (lines [21-33](https://github.com/cloudflare/computer/blob/main/packages/computerd/src/fuse/vfs.ts#L21-L33)) dynamically sets:

```typescript
Object.setPrototypeOf(SQLiteWorkspaceProvider.prototype, VirtualProvider.prototype)

```

This runtime inheritance allows the VFS creator to recognize the provider as a genuine `VirtualProvider` without bundling the VFS library into the Durable Object build.

### Core Filesystem Primitives

Each `VirtualProvider` method in `SQLiteWorkspaceProvider` delegates to low-level helpers in `packages/dofs/src/fs/` that operate directly on SQLite tables (`vfs_nodes`, `vfs_dirents`, `vfs_chunks`).

**Opening files** — The `openSync()` method (lines [35-70](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/provider.ts#L35-L70)) resolves inodes, handles create flags, and manages file descriptor state:

```typescript
// provider.ts – openSync()
const { read, write, truncate, append, create, exclusive } = parseFlags(flags);
const existing = resolveInode(this.db, path);
// … create handling …
const fd = this.#nextFd++;
this.#fds.set(fd, { path, position: append ? stat.size : 0, readable: read, writable: write, append });
return fd;

```

**Reading files** — `readFileSync()` (lines [66-98](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/provider.ts#L66-L98)) checks pending write buffers first, then assembles stored chunks into a `Buffer`:

```typescript
// provider.ts – readFileSync()
const node = resolveInode(this.db, path);
const buffered = getWriteBuffer(this.db, node.inode);
// … buffer handling …
const chunks = this.db.all(...);
// concatenate chunk bytes

```

**Writing files** — `writeRangeSync()` (lines [46-52](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/provider.ts#L46-L52)) persists data through `writeRangeSyncImpl`:

```typescript
// provider.ts – writeRangeSync()
const bytes = typeof data === "string"
  ? new TextEncoder().encode(data)
  : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
return writeRangeSyncImpl(this.db, path, bytes, offset, { mode }, this.now);

```

**Renaming and linking** — `renameSync()` (lines [21-34](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/provider.ts#L21-L34)) flushes pending buffers before mutating directory entries:

```typescript
// provider.ts – renameSync()
flushPendingUnderNode(this.db, oldPath, this.now);
flushPendingUnderNode(this.db, newPath, this.now);
// …
renameImpl(this.db, oldPath, newPath);

```

**Watching for changes** — The `watch()` implementation (lines [95-99](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/provider.ts#L95-L99)) polls `vfs_meta.rev` for revision changes:

```typescript
// provider.ts – watch()
return createWatcher(this.db, path, options, this.watchIntervalMs);

```

All methods return **POSIX-compatible stat objects** via `wrapStats`, providing `mode`, `size`, `mtime`, `atime`, and `ctime` fields that the FUSE driver expects.

### Connecting to the FUSE Driver

The FUSE driver in [`packages/computerd/src/fuse/driver.ts`](https://github.com/cloudflare/computer/blob/main/packages/computerd/src/fuse/driver.ts) receives the `NodeVirtualFileSystem` instance. Every kernel filesystem operation on the mounted path invokes the corresponding method on the provider, which executes SQLite queries against the Durable Object's database.

## Practical Usage Examples

### Mounting a FUSE Filesystem

```typescript
import { createNodeVirtualFileSystem } from "@cloudflare/computerd/src/fuse/vfs";

// Build a VFS backed by an in-memory DO SQLite store
const { vfs, db, stopSync } = await createNodeVirtualFileSystem();

// Pass vfs to the FUSE driver (e.g., in computerd CLI)
await mountFuse(vfs, "/myfs");

// Perform regular Node fs calls on the mount point
import { promises as fs } from "fs";

await fs.writeFile("/myfs/hello.txt", "Hello, world!");
const content = await fs.readFile("/myfs/hello.txt", "utf8");
console.log(content); // → Hello, world!

```

The provider transparently translates `writeFile` into SQLite chunk inserts and `readFile` into chunk reassembly queries.

### Watching for Changes

```typescript
import { watch } from "fs";

const watcher = watch("/myfs", (eventType, filename) => {
  console.log(`${eventType} on ${filename}`);
});

// Trigger a change:
await fs.writeFile("/myfs/notes.txt", "quick note");

// Output (after poll interval):
// change on notes.txt

```

The polling-based `watch` implementation guarantees that changes from upstream synchronization also surface to local FUSE clients.

## Key Implementation Files

| File | Role |
|------|------|
| [[`packages/dofs/src/provider.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/provider.ts)](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/provider.ts) | Core adapter implementing `VirtualProvider` on `Database` |
| [[`packages/computerd/src/fuse/vfs.ts`](https://github.com/cloudflare/computer/blob/main/packages/computerd/src/fuse/vfs.ts)](https://github.com/cloudflare/computer/blob/main/packages/computerd/src/fuse/vfs.ts) | VFS factory with prototype splicing and method extensions |
| [[`packages/computerd/src/fuse/driver.ts`](https://github.com/cloudflare/computer/blob/main/packages/computerd/src/fuse/driver.ts)](https://github.com/cloudflare/computer/blob/main/packages/computerd/src/fuse/driver.ts) | FUSE driver consuming the virtual filesystem |
| [`packages/dofs/src/fs/`](https://github.com/cloudflare/computer/tree/main/packages/dofs/src/fs) | Low-level filesystem operation implementations |
| [[`packages/dofs/src/testing.ts`](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/testing.ts)](https://github.com/cloudflare/computer/blob/main/packages/dofs/src/testing.ts) | `SQLiteTestStorage` for DO-backed SQLite |

## Summary

- **SQLiteWorkspaceProvider** implements the `VirtualProvider` interface to expose Durable Object SQLite storage as a POSIX-compatible filesystem.
- **Prototype splicing** (`ensureVirtualProviderPrototype`) bridges the Workers/Node.js boundary without polluting Durable Object builds.
- **Low-level SQLite operations** in `packages/dofs/src/fs/` handle file content as chunked blobs in `vfs_chunks` with metadata in `vfs_nodes` and `vfs_dirents`.
- **FUSE integration** occurs through `NodeVirtualFileSystem`, which the driver mounts and routes kernel calls through.
- **Change detection** polls `vfs_meta.rev` to provide `fs.watch` compatibility for local and remote modifications.

## Frequently Asked Questions

### How does SQLiteWorkspaceProvider handle file content storage?

The provider stores file content as **content-addressed chunks** in the `vfs_chunks` table, with metadata tracking chunk offsets and hashes in `vfs_nodes`. When reading, chunks are reassembled in order; when writing, new chunks are inserted and old overlapping ranges are invalidated. This deduplicates identical content across files automatically.

### Why is prototype splicing necessary instead of normal class inheritance?

`SQLiteWorkspaceProvider` lives in `packages/dofs` and targets **Cloudflare Workers**, where `@platformatic/vfs` cannot be imported due to Node.js dependencies. The `computerd` package runs in Node.js and needs the provider to appear as a `VirtualProvider`. Splicing the prototype at runtime in [`computerd/src/fuse/vfs.ts`](https://github.com/cloudflare/computer/blob/main/computerd/src/fuse/vfs.ts) satisfies both constraints: Workers builds stay clean, while Node.js builds gain full VFS compatibility.

### Can multiple FUSE mounts share the same Durable Object storage?

Yes—multiple `createNodeVirtualFileSystem()` calls can instantiate separate `SQLiteWorkspaceProvider` instances backed by the same `Database` or synchronized storage. Each provider maintains independent file descriptor state, but the underlying SQLite tables provide a single source of truth. Concurrent access requires the provider's internal locking or external coordination.

### What happens to unimplemented filesystem methods?

`SQLiteWorkspaceProvider` returns `ENOSYS` (function not implemented) for unsupported operations. This explicit failure mode prevents silent undefined behavior and makes compatibility gaps visible during development. Commonly stubbed methods include extended attribute operations and certain `ioctl` variants that lack SQLite equivalents.