DEV Community

Adarsh Pandey
Adarsh Pandey

Posted on

Driftless makes apps “offline-first” without painful boilerplate

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

GitHub Repo → Driftless

npm package → driftless-sync

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)

Collapse
 
jess profile image
Jess Lee

Cool, thanks for sharing