Skip to content

feat(blob-offloading): opt-in LRU blob cache with local GC and size cap #2278

Description

@liz709

Background

Blob offloading is now live in Dexie Cloud — large binary values are stored server-side and fetched on demand. The next natural step is giving apps control over how much blob data is kept locally, and automatically reclaiming space when the device gets full.

Problem

Currently, once a blob is fetched to the client it stays in IndexedDB indefinitely. There is no:

  • Size cap (device storage can grow unbounded)
  • Eviction policy (stale/unused blobs never leave)
  • Local GC (no way to reclaim space without clearing the whole DB)

For apps with large media libraries this becomes a real problem on mobile devices.

Proposed solution: opt-in LRU blob cache with local GC

Phase 1 — LRU eviction with size cap (recommended starting point)

API (tentative):

new Dexie('mydb').use(dexieCloud({
  databaseUrl: '...',
  blobs: {
    maxLocalSize: '500MB',   // evict LRU blobs when exceeded
    // optional future: ttl: '30d'
  }
}))

How it works:

  1. Track accessBlobRef gets a cachedAt: Date field updated on every read
  2. GC trigger — on app start (and periodically in a background task), measure total blob size in IndexedDB
  3. LRU eviction — if total > maxLocalSize, delete blobs in ascending cachedAt order until under threshold
  4. Cache miss handling — reading an evicted blob transparently re-fetches from server (invisible to the app, unless offline)

What changes

Layer Change Effort
BlobRef schema Add cachedAt?: Date Small
Blob read path Update cachedAt on access; handle cache miss with server fetch Medium
GC worker Periodic size check + LRU eviction Medium
Sync interaction Handle evicted blobs in sync pull correctly Medium
Tests Unit + E2E for eviction and cache miss Medium

Total estimated effort: ~2–3 weeks

Phase 2 (future)

  • TTL-based eviction (ttl: '30d')
  • Access-frequency heuristics (keep frequently-accessed blobs even if old)
  • User-visible "pin offline" API for specific objects/realms

Important constraints

  • Opt-in only — default behaviour is unchanged (blobs kept forever locally)
  • Offline safety — evicted blobs must not cause errors offline; the app must handle BlobRef in "uncached" state gracefully (e.g. show placeholder)
  • No race conditions — GC must not evict blobs mid-transaction
  • Transparent to app code — existing code using blob values should not need changes

Open questions

  1. Should maxLocalSize be a hard cap or a soft target (allow temporary overage)?
  2. How should the UI handle a cache miss while offline — error, placeholder, or queue for next sync?
  3. Should blobs in the currently-open/active view be protected from eviction?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions