Back to Articles
Offline-First Architecture: Lessons from Metaponic

PWA · Performance

Offline-First Architecture: Lessons from Metaponic

March 2024 · 11 min read

Metaponic’s Brain product needed to feel native on unreliable networks: greenhouse operators still open dashboards in basements, farms, and travel. We built the PWA so core flows — auth session, latest sensor snapshots, alarms, and map context — survived offline, then reconciled when connectivity returned.

What “offline-first” meant for us

Not “cache the marketing site.” It meant operators could open the app, see the last known state, acknowledge alarms, and queue mutations without a spinner of death.

  • App shell precached via Service Worker
  • IndexedDB for structured sensor history and alarm logs
  • Stale-while-revalidate for API GETs that power charts
  • Mutation queue for writes that must not be lost

Data model choices

We separated ephemeral UI state from durable domain snapshots. Charts could degrade to the last N points stored locally; alarms kept a clear “pending sync” badge so users never thought a local acknowledge had reached the server when it had not.

Maps, charts, and weight

Leaflet/OpenStreetMap tiles and Chart.js visualizations are heavy. We lazy-loaded map routes, capped offline tile zoom ranges, and avoided shipping the full chart stack on first paint. The Lighthouse wins came less from micro-optimizations and more from not downloading the world on boot.

Conflict policy

Offline writes need rules. For Metaponic we preferred server wins for sensor truth and client wins for user acknowledgements until sync, with explicit merge UI only where operators could collide. Most consumer apps skip this; industrial tools cannot.

Checklist before you promise offline

  1. Which screens are useless without network? Hide or degrade them honestly.
  2. What is the maximum IndexedDB footprint you accept on mid-range Android?
  3. How do you explain “saved locally” vs “synced” in the UI copy?
  4. Can QA reproduce airplane-mode journeys for every critical mutation?

Offline-first is a product promise. Architecture only works when that promise is visible in the interface.