NULLBIT
NULLBIT
Blog
Author: ALFRED

Offline-First Architecture: How It Works and When to Use It

Offline-first architecture explained: local reads and writes, sync queues, conflict resolution, and how it differs from local-first, plus when it pays off.

Offline-First Architecture: How It Works and When to Use It

Offline-First Architecture: How It Works and When to Use It

Hand-drawn offline-first architecture title card

Offline-first architecture is a way of building apps so the device’s own database is what the interface reads from and writes to, and the network is used only to synchronize in the background. The app keeps working with no signal, and the server catches up when a connection returns. This guide covers how the pattern works, how to sync and resolve conflicts, where it fits, and what it costs.

Nullbit
Build Apps That Keep Working Offline
Nullbit develops custom software tailored to business needs, including digital solutions designed to address operational challenges and support growth.
Explore Nullbit’s solutions

TL;DR

  • Offline-first apps read from a local database and write to it first. A sync layer moves changes to and from the server later.
  • Offline-first usually keeps the server as the authority. Local-first software goes further and treats the user’s device as the primary copy.
  • The hard parts are conflict resolution, retries, migrations and actions that truly need a live service, not storage.
  • It pays off for field work, poor networks and speed-critical apps. It is a poor fit when content must always be live.
  • Retrofitting offline support into an existing cloud-first app is expensive, so decide before the architecture hardens.

Table of Contents

What offline-first architecture means

An offline-first app is designed to perform all, or a critical subset, of its core functions without an internet connection. The word “first” matters. Connectivity is not treated as the normal state with offline mode bolted on as a fallback. The local store is the normal state, and the network is an optimization.

In practice that gives you three building blocks:

  1. A local database on the device that the UI reads from, always.
  2. A write path that saves changes locally before anything goes over the wire.
  3. A sync layer that sends queued changes to the server, pulls down new data, and deals with disagreements.

The user-facing effect is the part people notice. Screens load instantly because they never wait on a request. Forms save even in an elevator or a basement. Loading spinners mostly disappear, because the interface is not waiting for a server to answer.

Offline-first vs. local-first: where the authority sits

People searching for offline-first often also search for local-first software, and the two overlap. The difference is who holds the authoritative copy.

Offline-first architecture assumes the server is the authoritative source and queues changes for later synchronization. The server may confirm or reject what the device sends. Local-first software treats the local device as primary and uses techniques such as CRDTs (conflict-free replicated data types) to merge changes across devices.

The Ink & Switch research group set out the local-first idea in its 2019 essay. It describes software where the copy on the user’s device is the primary copy, with servers holding secondary copies for multi-device access. In ordinary cloud apps, by contrast, the server is authoritative and the client copy is a subordinate cache.

Offline-first Local-first
Primary copy Server User’s device
Local data is A working cache, queued for sync The source of truth
Typical conflict method Last write wins, server decides CRDTs, merge across devices
Main goal Keep working without signal Data ownership, collaboration, longevity
Server role Authority Convenience for sync and backup

Most real products mix both. Orders that a back office must approve fit the server-authoritative model, while a shared checklist that several people edit fits the local-first model. Many systems use both approaches for different data, so treat this as a per-dataset decision, not a company-wide ideology.

How reads and writes work without a connection

Reads always hit the local database

Android’s architecture guidance says offline-first apps read directly from a local database for immediate access. The UI observes that database through a reactive API, so when the sync layer updates a row, the screen refreshes without any extra wiring. The network is never in the read path.

Three ways to handle writes

The same Android guide lists three write strategies, and the choice is a product decision as much as a technical one:

  • Online-only writes. The action fails or is disabled without connectivity. Right for a bank transfer.
  • Queued writes. The change is stored locally, then a persistent queue sends it when the network returns.
  • Lazy writes. The change is saved locally and reconciled with the server later, accepting that the two may briefly differ.

Flutter’s documentation makes the same point: the choice between online-only and offline-first writing depends on the application’s use case. Pick per action. A field technician’s inspection form should be queued. A payment confirmation should not.

Track what still needs to sync

A simple technique from Flutter’s guidance is a synchronized flag on each record. It marks whether the item has reached the server. With that flag, your sync job can find unsent changes after a crash, a restart or a week without signal, and retry them safely.

Synchronization and conflict resolution

Sync is where offline-first projects succeed or stall. Two questions drive the design: when does the sync run, and what happens when two edits collide?

Pull, push and background queues

Android’s guide describes synchronization as pull-based, push-based, or both, and notes that WorkManager can manage persistent background queues with retries. Flutter’s guide adds that sync can run in the background or be triggered explicitly by the user. A manual “sync now” button is cheap insurance, since it gives users some control and gives your support team a first diagnostic step.

Whatever platform you use, a sync queue should have these properties:

  • It survives app restarts and device reboots.
  • It retries with backoff instead of hammering a weak connection.
  • It is idempotent, so a retry never creates a duplicate order.
  • It reports state, so the UI can show what is pending and what failed.

Last write wins

The default for many mobile apps is Last Write Wins. Per the Android documentation, timestamp metadata is attached to local writes and the network source of truth reconciles discrepancies by accepting the latest timestamp. It is simple and predictable. It is also lossy: if two people edit the same record offline, one edit silently disappears. That is acceptable for a profile setting and unacceptable for a clinical note or a shared quote.

For data where losing an edit costs money or trust, you have better options:

  • Field-level merging, so changes to different fields of one record both survive.
  • Append-only records, such as a log of inspections or stock movements, which cannot conflict in the first place.
  • Explicit review, where the app flags a conflict and asks a person to choose.

CRDTs for real collaboration

When several people edit the same document or list, CRDTs are the research-backed answer. Ink & Switch names them as a potential foundation for local-first software, supporting collaboration across multiple devices. Their work on Peritext shows how much care rich-text collaboration needs, since a general JSON CRDT such as Automerge has shortcomings for representing formatted text. Their PushPin research also showed local-first apps syncing over Bluetooth or local Wi-Fi without needing the internet at all.

The cost is conceptual. This approach means moving away from consensus algorithms toward eventual consistency, and your team has to be comfortable reasoning about data that is correct eventually, not instantly.

Design choices that make it feel reliable

Users judge an offline-first app by whether it is honest about what is happening. A few decisions carry most of the weight.

Show sync state, not spinners. Expo’s local-first guide points out that some actions, such as sending an email, complete only when a remote service accepts them. It recommends recording states such as queued, sending, accepted and failed. Display those states. “Saved on this device, waiting to send” is a reassuring message. A frozen button is not.

Four states shown for queued remote actions

Be explicit about online-only features. Android’s guidance suggests handling these by disabling the write or telling the user they are offline. Do it where the user acts, not in a banner they have to interpret.

Keep the UI simple to build. Expo presents local-first as a developer-experience gain too: because screens read from a local database, you no longer model every request as loading, loaded or error, and sync runs separately.

Plan migrations early. Devices can stay offline for weeks, so a server schema change has to tolerate old clients that sync late. Version your local schema, version your API, and test an app that has been offline across two releases.

Mind the network around the app. Apps that run in warehouses, branches or sites depend on the local network too. Some teams pair offline-first apps with a sound edge networking strategy so that local traffic and failover behave well when a site’s uplink drops.

The seven ideals of local-first software from the 2019 Ink & Switch essay are a good checklist for ambition: no spinners, network independence, real-time collaboration, privacy and user ownership among them. You will not need all seven, but knowing which you are choosing to skip keeps decisions deliberate.

When offline-first is the right call

Android’s documentation says the pattern suits work in unreliable networks, such as field service, transit, healthcare and construction, and apps where responsiveness is critical. Locize describes the typical field-service flow: viewing customer data, filling forms, saving orders, and syncing when connected. Expo adds that local-first is especially suited to collaborative or multiplayer applications.

It is less suitable when:

  • Content must always be live, such as market prices or live inventory that others depend on in the moment.
  • The cost of synchronization and conflict resolution outweighs the user benefit.
  • Actions are inherently online, such as payments and third-party confirmations.

A quick test: ask what a user loses if the app stops for ten minutes with no signal. If the answer is “a job site’s worth of work”, build offline-first. If the answer is “nothing important”, a well-cached online app may be enough.

What it costs and where teams get surprised

The academic case is blunt. Kleppmann and colleagues note that retrofitting offline support into existing cloud-first apps is technically challenging, because server-centric architectures do not adapt easily to offline editing. That is the main budget risk we see in the pattern: teams treat offline as a feature to add in the last sprint, then discover that the data model, API and permissions all assumed a live server.

Expect extra effort in these places:

  • Data model. Records need stable client-generated IDs, timestamps or version markers, and sync status.
  • API. Endpoints must accept batches, repeated requests and late arrivals.
  • Testing. You must test airplane mode, flaky connections, clock drift, long offline periods and interrupted syncs.
  • Security. Data stored on a device needs encryption and a plan for lost devices and revoked access. If your data is subject to location rules, see our guide to data residency requirements.

If you are still deciding between a native app, a PWA and a web app, our guide on choosing mobile app, PWA or web app walks through the trade-offs. When your offline app has to exchange data with ERP, CRM or other back-office systems, our system integration practices matter as much as the sync engine.

Our perspective

We build custom software and treat AI as part of the core of a system rather than an add-on, and offline-first questions come up whenever a business process runs outside the office. Our view is that the pattern is a business decision before it is a technology one.

Start from the process. Which actions must never be blocked? Which data can tolerate a brief mismatch, and which cannot? Those answers decide whether you need simple queued writes, field-level merging or full CRDTs. Many teams over-engineer here, reaching for the most sophisticated merge approach when append-only records would remove the conflict entirely.

Our perspective

We also stay technology-agnostic. Room, SQLite, a sync framework or a CRDT library can all be correct choices, and the right one depends on your devices, your team and how you will maintain it for years. What we insist on is measurable outcomes: fewer failed jobs in the field, faster screens, fewer support tickets about lost data. Define those before building, and test sync under bad conditions before launch, not after.

And decide early. Offline behavior woven into the data model from day one is far cheaper than a retrofit.

— Matija

Planning an offline-capable app with us

If you are weighing an offline-first build, the cheapest first step is usually a proof of concept that tests your hardest sync scenario on real devices. Our proof-of-concept development starts from €5,000 one-off. For a full product, our mobile app development and custom software development teams work on either an agile engagement at €5,000 to €40,000 per month or a fixed-price turnkey project at €5,000 to €60,000 one-off, described on our cooperation page.

Nullbit

If you would rather talk it through first, contact us through nullbit.co with the process you want to keep running offline.

FAQ

Is offline-first the same as local-first?

No, though they overlap. Offline-first usually keeps the server as the authoritative source and queues device changes for later sync. Local-first treats the user’s device as the primary copy and often uses CRDTs to merge edits across devices. Many products use both for different kinds of data.

What is the best way to resolve sync conflicts?

It depends on the data. Last Write Wins, which accepts the latest timestamp, is common in mobile apps and fine for low-stakes settings. For records where losing an edit matters, use field-level merging, append-only records, or CRDTs for collaborative documents.

Which apps should not be offline-first?

Apps whose content must always be live, and apps where sync and conflict handling cost more than the benefit, are poor fits. Individual actions can also stay online-only, such as a bank transfer. In those cases, disable the action or tell the user they are offline.

Can I add offline support to an existing app later?

You can, but it is hard. Research from Kleppmann and colleagues notes that server-centric architectures do not adapt easily to offline editing. Expect changes to the data model, API and testing, not just a new cache layer.

How do I show users that their changes are safe?

Track the state of each change and display it: queued, sending, accepted or failed. Expo’s guidance recommends these states for actions that depend on a remote service. Pair them with a clear message when something fails and needs the user’s attention.

Sources

Tags
offline first architecture
Stay ahead of the competition

Exclusive insights that drive change.

Get access to proven methodologies for digital growth, AI tool implementation, and AI product development.

  • Weekly digital strategy analyses
  • Advanced insights into AI trends and technology solutions

Your privacy is a priority. You can unsubscribe at any time.