Skip to content

Persistence and recovery

A write can finish before its changes reach persistent storage. Synchronize important changes and wait for success before telling a user their work is saved.

Persistence is local to this browser and origin. It does not upload files or copy them to another device.

The buffer mode controls how the VFS accesses file contents. Both modes use OPFS storage. A memory buffer is not a temporary, memory-only filesystem.

Disk bufferDefault
writeYour application
direct block I/O
OPFS volumeFile data blocks

No full RAM copy of file contents. Synchronization flushes pending data and metadata.

Memory bufferOptional
writeYour application
cache
RAMFile contents
copy at sync
OPFS volumeFile data blocks

Each write also appends to an OPFS recovery log. On recovery, the VFS replays recoverable records into RAM.

Both modes use persistent OPFS storage. These are file-data paths, not flush guarantees or a complete view of metadata and bookkeeping.

Direct mounts and worker clients default to bufferMode: 'disk' and localDurabilityMode: 'balanced'. Disk mode avoids a full RAM copy of file contents. Balanced mode schedules synchronization about 150 ms after the first dirty change, but a busy or suspended worker can delay it. Continue using explicit fsync or volume synchronization at meaningful save points.

For memory caching with explicitly managed synchronization, select { bufferMode: 'memory', localDurabilityMode: 'relaxed' }. Both buffer modes persist to OPFS. The PGlite adapter’s separate relaxedDurability option is unchanged. See storage modes explained for the tradeoffs.

Buffering chooses the data path. Local durability chooses when the VFS requests a flush of pending changes.

Local durability What triggers synchronization? What to remember
relaxed Explicit synchronization or an orderly close. Your application chooses save points.
balanced, default A timer scheduled about 150 ms after the first dirty change, plus explicit synchronization or an orderly close. Worker scheduling or suspension can delay the timer. It is not a maximum loss window.
strict Also flushes appended memory-mode recovery-log records immediately. It does not flush every disk-buffered write. Keep explicit save points.
Walk through a save

With the default disk buffer and balanced durability. Illustrative steps, not measured timings.

  1. Write returns May still be pending

    Your application can read the updated file. The write returning does not establish an explicit save boundary.

  2. Synchronize successfully Save boundary

    Call syncSync() in the worker, or await volume.sync() through the worker client. This synchronizes the volume's pending data and metadata.

    If synchronization fails, report the error. Do not show the work as saved.

  3. Close and reopen Resume locally

    Successfully await closeVfs(). Reopen the same volume in the same browser and origin, then await ready before reading the saved files.

New writes after synchronization need another save boundary. Local storage can still be cleared or evicted. Export important work as a backup.

For a direct OpfsVfs mount in a dedicated worker, call vfs.syncSync() to synchronize the volume. vfs.fsyncSync(fd) currently uses the same volume-wide synchronization after validating the file descriptor.

With an initialized worker client, await the asynchronous call:

import type { OpfsVfsWorker } from '@opfs-vfs/opfs-vfs/worker';
// Call after your writes finish. Rejection means the save failed.
async function save(volume: OpfsVfsWorker): Promise<void> {
await volume.sync();
// Only now tell the user these changes have been saved locally.
}

Await closeVfs() when finished with the volume. Closing a file descriptor alone is not a substitute for synchronizing the volume. Browser shutdown may interrupt work, so do not rely on a page-close handler as your only save point.

On the next mount, the VFS checks the volume and attempts recovery before ready resolves. A recovery log, also called a write-ahead log or WAL, records changes that may need to be replayed. Recovery cannot promise to restore every unsynchronized write.

The VFS exposes local persistence status, including dirty pages, pending WAL bytes, state, and last error. The default recovery policy salvages recoverable WAL damage; recoveryMode: 'fail-stop' lets an application decide instead. Do not automatically delete a volume after a mount error.

Synchronization does not protect against clearing site data or browser storage eviction. Offer an export or backup for important files.

A cleanly closed volume can reopen using disk buffering. If a previous session left a nonempty memory recovery log, a disk mount rejects it with EBUSY to avoid discarding recoverable changes.

Reopen that volume with bufferMode: 'memory', await ready, and successfully await closeVfs(). Then reopen it with the disk default. Do not delete recovery logs or reset the volume to bypass the error.