The phrase "offline-first" is one of those rare bits of industry jargon that means almost the opposite of what it sounds like. It does not mean "works offline, then syncs when you reconnect." It means: the local device is the source of truth, the network is an optional accessory, and the app is designed so that whether you ever come online is irrelevant to the core experience.
Drimin takes that framing literally. The app declares no INTERNET
permission. Not "doesn't use the network by default," not "works offline when it
has to." Cannot. The architecture follows from that constraint in ways that surprise
engineers more used to cloud-shaped apps.
1. The database is the source of truth, not a cache
In a cloud-first app, the local database is a cache — an optimisation on top of the real store, which lives behind an API. Every screen reads from the cache while background workers reconcile with the server. Conflict resolution, eventual consistency, and "I refreshed and my edit disappeared" bugs are the price.
In an offline-first app, the database is the source of truth. There is no server to ask. A row that was just inserted is, definitionally, current. The whole category of "stale read" bugs becomes structurally impossible.
This has downstream simplifications. Drimin uses a single Drift database, encrypted with SQLCipher (see SQLCipher in Flutter, without the headache), and exposes it through repositories that return streams of typed model objects. The UI subscribes; mutations write; the stream emits. There is no synchronisation layer because there is nothing to synchronise with.
2. There are no connectivity error states
Open most modern apps in airplane mode and you'll see a familiar pattern: a spinner, a banner ("No internet connection"), a sad-cloud illustration, a retry button. All of that UI is dead weight in an offline-first app, because it cannot be triggered. Removing it is more than a cosmetic win — it removes a category of code paths that had to be reasoned about, tested, and localised. The "happy path" becomes the only path.
Drimin has no loading spinners on the home screen. Not because we made them instant; because there's nothing to wait for. The database open is a few milliseconds at cold start, and from then on every screen reads from it synchronously.
3. There are no auth flows
Auth is the API contract enforcing identity for a backend. No backend, no auth. Drimin has no account, no email, no password, no token refresh, no sign-in-with-Google, no anonymous-then-upgrade flow. The first launch is a one-screen onboarding (your daily goal and preferred cup size) and you're in.
For a hydration tracker this is freeing. For other product categories, it is the single hardest question to answer honestly. If you don't have a server, what does "your account" even mean? In Drimin's case, the answer is: your phone is your account. The app's data lives only there. We have no way to "log you in to a new device" because there is nothing on our side to log you in to. That is a feature. For some classes of app it would be a non-starter; offline-first is a choice with real product implications.
Pick this architecture deliberately. It removes whole categories of code — and whole categories of capability. The trade is wonderful when it fits, painful when it doesn't.
4. There is no remote config, no kill switch, no A/B test
This is where the discipline gets uncomfortable. Modern mobile development leans heavily on remote configuration: feature flags, server-tuned thresholds, A/B experiments, killswitches for misbehaving features. All of those require a network round trip. None of them exist in Drimin.
The trade is that bad releases are truly bad. You cannot roll back a misconfigured timer from your dashboard at 2am; you must ship a new version through Play Store review and wait for users to update. The mitigation is the same one software shipped on the way for the previous fifty years: release more carefully. Staged rollouts. Strong unit and widget tests. A long beta cohort. Internal dogfooding. Fewer features, but each shipped with the knowledge that it will be live, unmodified, on the user's device until they choose to update.
5. The UI can be honest about what it knows
A surprising number of UX patterns exist to mask the latency of network calls. Optimistic updates, skeleton loaders, "checking your data" toasts, snackbars that appear ten seconds after the action you took. All of those are coping mechanisms for a contract the user never agreed to: "your action will eventually take effect, probably."
In an offline-first app, the action has taken effect by the time the next frame renders. The orb's water level on Drimin's home screen rises during the same frame as the tap that caused it. No undo-on-failure. No "saving…". The interface gets to be honest. The design language that follows from that is calmer than any spinner-heavy app can be.
6. Export is the only sync
"But what about a new phone?" is the fair question. The answer in an offline-first app is — explicitly — export. The user produces an artifact (a CSV, a JSON, an encrypted blob) and moves it themselves. There is no automatic cloud sync because there is no cloud, and offering a half-baked one would betray the architecture.
Drimin's near-term roadmap includes local export of your encrypted database, plus a decrypted JSON for users who want to import it elsewhere. Both flows are user- initiated and visible. There is no "background sync" because there is no background sync; the data does not leave the device without you exporting it.
When it fits, and when it doesn't
Offline-first is the right shape for apps where:
- The data is personal and small — logs, notes, intake, journals.
- There is no collaboration model. One user, one phone, one dataset.
- The product can credibly say "you don't need an account."
It is the wrong shape when the product's value is multi-device, collaborative, or depends on aggregated data from many users. Choose the architecture honestly. A bad fit between offline-first and a collaborative product is worse than either pure cloud or pure local-first.
For the philosophical companion to this engineering piece, see Free software, zero telemetry. And for the privacy guarantees this architecture unlocks, see Privacy-first by default.