Introduction
Have you ever been on an important delivery, a medical visit, or even just using a simple form, only to hit a spot with no network?
You fill in all the information, tap “Submit,” and… nothing.
That’s lost data. And it’s frustrating.
Today I want to introduce you to Driftless — a library built with the sole purpose of solving that problem. No more lost user actions. No more missing records. No more “Oops, network is gone” and hoping for the best.
Driftless vs Alternatives — Comparison Table
Feature / Capability | Driftless | PouchDB + CouchDB Replication | RxDB | CRDTs (Yjs / Automerge) | Workbox + Background Sync | Firebase / Supabase Offline Features |
---|---|---|---|---|---|---|
Local queue of user actions | ✅ (IndexedDB, explicit queue) | ✅ (with CouchDB) | ✅ | ✅ (for CRDT-backed data) | ⚠️ (background sync queues raw requests, but limited visibility) | ✅ (for certain SDKs, e.g. Firestore offline) |
UUID-based IDs / Versioning Metadata | ✅ | ✅ (via document revisions) | ✅ | ✅ | ❌ | ✅ (depending on backend) |
Conflict detection / customizable conflict resolution | ✅ (via onConflict / event) |
✅ (manual resolution, CouchDB revision merge) | ✅ (some support) | ✅ (CRDT merges automatically) | ❌ / Very limited | ⚠️ (depends on product; sometimes “last write wins” or use optimistic concurrency) |
Visibility & Inspectability of queued items | ✅ (can inspect IndexedDB queue) | Partial (replication logs, tools) | ✅ (reactive local DB) | ❌ / not for raw actions | ❌ (service worker under-the-hood) | Partial |
Lightweight footprint | ✅ (designed to be minimal core + adapters) | Heavier (bundle + server replication support) | Heavier (reactivity, plugin layers) | Medium (for CRDT operations) | Lightweight for caching; lacks full conflict logic | Variable; SDKs tend to include a lot of features |
Framework-agnostic | ✅ | ✅ | ✅ | Mostly, if adapted | ✅ for caching; data sync usually integrated per-framework | SDK tied, some frameworks only |
Dependency on backend choices | Low — any backend that can respond with ok / conflict works |
High — you typically need CouchDB or compatible server | Medium/High — replication plugin/backends required | High — need CRDT-aware servers or peers | Low for caching; high for data consistency | Medium — depends on backend features and SDK availability |
UI state hooks / status support | ✅ (offline, queued, syncing, conflict, success) | Partial / custom | ✅ (if you build) | ❌ / needs extra work | ❌ (mostly invisible to UI) | ✅ (some SDKs provide) |
Compliance / audit log friendliness | ✅ (versioning + metadata) | Medium (replication logs, but restructuring needed) | Medium | Medium-Low | Low | High (stores persistent data + metadata) |
Key Takeaways
-
Where Driftless excels:
- Clear, inspectable local queue (IndexedDB)
- Conflict resolution via
onConflict
+ custom merge - Lightweight, framework-agnostic API
- Good metadata (UUIDs, versions) for auditing
-
Where alternatives may be better:
- If you already use CouchDB (PouchDB) and need live replication across devices
- If you need real-time collaborative editing (CRDTs like Yjs or Automerge)
- If your backend / product already includes offline SDKs (Firebase, Supabase) and you want to leverage those
The Problem: Offline Isn’t Enough
Modern Progressive Web Apps (PWAs) help with offline caching of pages and assets. Tools like service workers will do a great job at letting users still open your site when they lose connectivity. But what about:
- Submissions (orders, forms, reports) done while offline
- Handling conflicts (two devices make different updates while offline)
- Letting users know what’s happening with their offline work
- These are major gaps in many apps — especially in healthcare, logistics, delivery, etc.
What is Driftless?
Driftless is a framework-agnostic, offline-first sync library with built-in conflict resolution and visual sync states. It provides:
A local queue of actions stored in IndexedDB
UUID-based IDs and versioning to keep uniqueness and track conflicts
REST adapter today, with plans for GraphQL / gRPC adapters
Conflict detection: either automatic merge (via custom handler) or conflict event for UI to handle
Hooks / components for frameworks (React etc.) so you can show status: offline, queued, syncing, success, conflict
Use Cases
Here are some real-world scenarios where Driftless shines:
- Healthcare delivery partner tries to deliver medicine in a building basement → network is down → action is queued → once online, syncs automatically
- Warehouse staff scanning or recording inventory where signal is weak
- Field agents in remote areas submitting reports, photos, etc.
- E-commerce cart flows where customers add items while offline
How Driftless Works — Architecture
In short:
- User does something → call store(...)
- The action is saved locally (IndexedDB) with a unique ID and version
- If online, Driftless tries to push queued items via adapter
- If adapter responds with conflicts or errors, Driftless handles them via onConflict or by raising an event
- After successful sync, items are removed from the queue
Why This Matters
For anyone building apps that must work in low-network or offline conditions, Driftless:
- Reduces data loss
- Improves user trust (“my action went through” feedback)
- Saves you from writing tons of boilerplate for retries, local storage, and syncing
- Makes conflict resolution clearer and manageable
What PWAs Do Well
Progressive Web Apps (PWAs) give you offline capability for loading and caching:
- Service workers can cache HTML, JS, CSS, API responses → so your app loads even when offline.
- Tools like Workbox background sync can retry failed requests once the network is back.
- This makes PWAs amazing for read-only offline apps (news, blogs, docs, dashboards).
But PWAs don’t solve some critical problems for user-generated data:
1. Conflict resolution
- If two users edit the same record offline → PWAs don’t tell you how to merge those changes.
- Driftless has onConflict API so you can decide: last-write-wins, merge, or prompt user.
2. Transparent queue management
- Service workers queue requests internally (black box).
- With Driftless, the queue is explicit in IndexedDB → devs can inspect, retry, clear, or log actions.
3. Versioning & metadata
- Driftless adds UUIDs, timestamps, versions to every action → critical for audit logs (healthcare, logistics).
- PWAs just replay a POST request without extra context.
4. UI integration
- PWAs don’t expose “sync state” to your app UI.
- Driftless provides hooks/components → your app can show Offline, Queued, Syncing, Conflict banners.
5. Enterprise scenarios
- In healthcare or airlines, regulators require audit trails of actions taken offline.
- Driftless gives you structured events and data that can be logged. PWAs alone can’t.
How They Fit Together
Think of them as complementary:
- PWA = your app shell + content loads offline
- Driftless = user actions and edits are safely stored, synced, and resolved
So, a robust offline-first app will often use both:
- PWA service worker for caching & offline loading
- Driftless for data queueing, syncing, and conflict handling
Thanks for reading!
Top comments (1)
Cool, thanks for sharing