Intermittent OPFS Data Loss in Edge with SQLite-WASM: Causes and Fixes


Understanding OPFS Data Loss in Browser-Based SQLite Applications

The core issue revolves around unexpected data loss in web applications using SQLite-WASM with the Origin Private File System (OPFS) API, particularly in Microsoft Edge. Developers report that OPFS-stored data disappears under unclear conditions, while data in LocalStorage remains intact. This behavior undermines the reliability of applications requiring persistent client-side storage, such as note-taking apps, collaborative tools, or offline-first solutions. The problem is exacerbated by its intermittent nature (occurring roughly monthly) and the lack of clear reproduction steps, making root cause analysis challenging.

Technical Context: OPFS and Browser Storage Tiers

OPFS is part of the File System Access API, designed to provide web apps with a private, sandboxed file system tied to the origin (domain). Unlike LocalStorage (limited to 5–10 MB) or IndexedDB (asynchronous key-value storage), OPFS allows synchronous file operations critical for porting low-level libraries like SQLite to WebAssembly. However, browser vendors implement OPFS with varying storage eviction policies. By default, OPFS data is considered "best-effort" persistent and may be purged under storage pressure unless the app explicitly requests persistent storage permissions. This distinction is often overlooked, as LocalStorage and IndexedDB are subject to different eviction rules.


Root Causes of OPFS Data Loss in Edge

1. Missing or Denied Persistent Storage Permissions

Browsers classify storage into temporary (default) and persistent tiers. Temporary storage can be cleared without user interaction when the browser detects low disk space, prolonged inactivity, or during routine cleanup. Persistent storage requires explicit user consent via navigator.storage.persist(). If an app fails to request this permission or the user denies it, OPFS data remains vulnerable to automated eviction. Edge further complicates this by tying persistent storage grants to other permissions (e.g., notifications), creating unexpected dependencies.

2. Third-Party System Cleanup Utilities

Utilities like CCleaner, AVG PC TuneUp, and BleachBit aggressively delete browser cache and temporary files. These tools often misclassify OPFS data as disposable "Internet Cache" or temporary files, especially when they lack awareness of modern web standards like OPFS. Windows 11’s built-in Storage Sense feature similarly targets temporary files, and its heuristics may erroneously include OPFS directories. Unlike cookies or LocalStorage, OPFS directories are stored as physical files on disk (e.g., in Edge’s WebKit/OriginPrivateFileSystem directory), making them susceptible to file-level cleaners.

3. Browser-Specific Bugs and Storage Quirks

Edge’s implementation of OPFS and its integration with Windows storage management subsystems may have undiscovered bugs. For instance:

  • Inconsistent Permission Persistence: Edge might revoke persistent storage grants after browser updates, OS reboots, or profile resets.
  • OPFS Directory Corruption: Silent failures during write operations (e.g., due to abrupt browser shutdowns) could leave databases in a corrupted state. However, SQLite-WASM typically retains corrupted files unless explicitly deleted, making this less likely.
  • Storage Pressure Algorithms: Edge’s storage eviction logic might prioritize OPFS data over other storage mechanisms under memory constraints, even when persistent permissions are granted.

4. Application Architecture Flaws

While not directly causing data loss, certain design choices amplify the impact:

  • Lack of Redundant Backups: Relying solely on OPFS without periodic exports to IndexedDB or cloud sync increases data vulnerability.
  • Inadequate Error Handling: Failing to detect NotFoundError exceptions when accessing OPFS files leaves users unaware of data loss until they attempt to reload the app.

Comprehensive Solutions for Preventing OPFS Data Loss

Step 1: Enforce Persistent Storage Permissions

Requesting Permissions:

  • Explicit User Gesture: Trigger navigator.storage.persist() after a user interaction (e.g., clicking "Save Data" button) to comply with browser security policies. Example:
    document.getElementById('saveButton').addEventListener('click', async () => {
      const isPersistent = await navigator.storage.persist();
      alert(isPersistent ? 'Storage is persistent!' : 'Storage may be cleared.');
    });
    
  • Fallback Strategies: If persistent storage is denied, warn users about data volatility and offer alternatives like exporting to downloadable files or cloud storage.

Monitoring Permission States:

  • Use navigator.storage.persisted() to check current status during app initialization:
    async function checkStoragePersistence() {
      const isPersistent = await navigator.storage.persisted();
      if (!isPersistent) {
        showWarningBanner('Enable persistent storage to prevent data loss.');
      }
    }
    

Step 2: Mitigate Third-Party Cleanup Risks

User Education:

  • Provide documentation instructing users to:
    • Exclude Edge’s application data directory from cleanup tools.
    • Disable Windows Storage Sense (Settings > System > Storage > Storage Sense).
    • Avoid utilities like CCleaner that lack OPFS awareness.

Developer Workarounds:

  • Data Redundancy: Regularly mirror OPFS data to IndexedDB, which is less likely to be purged by file cleaners. Example sync logic:
    async function backupToIndexedDB() {
      const opfsFile = await getOPFSFileHandle();
      const content = await opfsFile.text();
      const db = await openIDB('backups');
      await db.put('backups', content, 'latest');
    }
    
  • Checksum Validation: Store SHA-256 hashes of critical databases in LocalStorage and validate them on app startup to detect tampering or deletion.

Step 3: Address Edge-Specific Quirks

Testing Across Browsers:

  • Replicate the app in Chrome, Firefox, and Safari to isolate Edge-specific issues. Use feature detection for OPFS:
    if ('storage' in navigator && 'getDirectory' in window.showDirectoryPicker) {
      // OPFS is supported
    }
    

Edge Bug Mitigations:

  • File Locking: Use FileSystemSyncAccessHandle for atomic writes, reducing corruption risks during abrupt closures.
  • Storage Pressure Monitoring: Listen to quotachange events to warn users before data eviction:
    navigator.storage.addEventListener('quotachange', (event) => {
      console.log('Storage quota changed:', event);
      alert('Free space is low—export data to prevent loss.');
    });
    

Step 4: Implement Robust Recovery Mechanisms

Automated Backups:

  • Schedule incremental backups using the Background Sync API or Service Workers:
    // In service worker:
    self.addEventListener('periodicsync', (event) => {
      if (event.tag === 'opfs-backup') {
        event.waitUntil(backupToIndexedDB());
      }
    });
    

Corruption Recovery:

  • Embed SQLite’s built-in integrity checks:
    PRAGMA integrity_check;
    

    If corruption is detected, restore from the last known good backup.

Step 5: Collaborate with Browser Vendors

  • File Edge Bug Reports: Detail the issue with steps to reproduce, including Edge version, OS build, and installed cleanup tools.
  • Engage with Standards Bodies: Advocate for clearer OPFS eviction policies in the W3C Storage Working Group to prevent divergent browser implementations.

By systematically addressing permissions, third-party risks, browser quirks, and recovery workflows, developers can significantly reduce OPFS data loss incidents. Persistent storage permissions remain the first line of defense, but a layered approach combining user education, redundancy, and vendor collaboration is essential for mission-critical applications.

Related Guides

Leave a Reply

Your email address will not be published. Required fields are marked *