Disciplines · Decisions (ADRs)

ADR-0011: Offline Caching and Sync Strategy

OSHUN must remain useful under intermittent or absent network conditions across:

Accepted · 2026-02-16
12sections5 minread

On this page

Status: Accepted Date: 2026-02-16 Authors: OSHUN Platform Engineering, OSHUN Mobile Engineering, OSHUN Web Engineering Reviewers: Domain Leads (Tara, Veritas, Nyx, Arete) Supersedes: N/A Superseded by: N/A

Context and Problem Statement#

OSHUN must remain useful under intermittent or absent network conditions across:

  • mobile (iOS/Android)
  • website/PWA

Repository evidence shows strong but fragmented offline approaches:

  • Tara web SW uses cache-first for static/audio and network-first for navigation.
  • Veritas web includes service worker caching plus background sync queue patterns.
  • Nyx PWA uses Workbox runtime caching (NetworkFirst API, CacheFirst assets/fonts/images) and local data persistence.
  • Veritas mobile has offline article cache + sync queue + eviction logic.
  • Tara mobile includes queue-driven download manager and storage controls.

We need one OSHUN policy for what to cache, how to sync writes, and how to handle failures safely.

Decision Drivers#

  • Reliability for core shell journeys during connectivity loss.
  • Consistency across mobile and web/PWA behavior.
  • Safety for write operations and conflict handling.
  • Performance through predictable caching and prefetch policies.
  • Storage discipline on constrained mobile devices.
  • Observability for offline failure and recovery behavior.

Considered Options#

Option 1: Network-Only Dynamic Data, Minimal Offline#

Description: cache static assets only; all dynamic content requires network.

Pros:

  • ✅ Lowest complexity
  • ✅ Minimal cache invalidation risk

Cons:

  • ❌ Poor user experience in weak connectivity
  • ❌ Shell feels fragile in daily mobile contexts
  • ❌ Misses key OSHUN reliability goals

Option 2: Cache-First for Most Data#

Description: aggressive cache-first for static and dynamic data.

Pros:

  • ✅ Very fast perceived loads
  • ✅ More content available offline

Cons:

  • ❌ High staleness risk for time-sensitive data
  • ❌ Complex invalidation and consistency issues
  • ❌ Risky for personalized/entitled content

Option 3: Hybrid Policy - Cache-First Static, Network-First Dynamic (Chosen)#

Description: static assets use cache-first; dynamic personalized/API data uses network-first with stale fallback; write operations queue offline and sync later.

Pros:

  • ✅ Strong balance of freshness and resilience
  • ✅ Aligns with proven patterns already in repo
  • ✅ Better control over stale-data risk
  • ✅ Clear policy matrix for implementation and QA

Cons:

  • ❌ Requires robust sync queue/conflict handling
  • ❌ More moving parts than minimal offline strategy

Decision Outcome#

Chosen option: Option 3 - hybrid offline strategy.

Normative Cache Policy Matrix#

Data Class Examples Strategy Notes
Static shell assets JS/CSS/fonts/icons/manifest CacheFirst Versioned, immutable cache keys
Navigation documents shell routes NetworkFirst + offline fallback return cached/offline page on failure
Dynamic API read data home/activity/search/domain cards NetworkFirst + stale fallback short TTL and explicit staleness metadata
Media audio/images/star maps/downloads CacheFirst or managed download cache entry caps + eviction required
Auth/session endpoints login/refresh/logout/entitlements NetworkOnly never served from cache
Mutating writes save/unsave, settings, check-ins queue offline + replay idempotency required

Offline Write Queue Rules (Mandatory)#

  • Queue all non-destructive writes when offline.
  • Each queued op includes:
    • stable operation id
    • operation type
    • payload
    • creation time
    • retry count
  • Replay on reconnect with exponential backoff + jitter.
  • Stop retry after max attempts and surface recoverable UI state.
  • Queue processor must be idempotent-safe to prevent duplicate side effects.

Conflict Resolution Rules#

  • Default strategy: server-authoritative merge for shared resources.
  • Local optimistic state must rollback on authoritative rejection.
  • For preference toggles, last-write-wins with server timestamp.
  • For list toggles (save/unsave), de-duplicate by operation id and latest intent.

Storage and Eviction Rules#

  • Define per-platform cache budgets and hard ceilings.
  • Evict using policy by class:
    • media: LRU with bookmark/pin protections where applicable
    • feed/API cache: TTL-based purge + LRU fallback
  • Display user-visible storage usage and allow manual cleanup actions.

Prefetch Rules#

  • Prefetch only on adequate connection (prefer Wi-Fi, respect data saver).
  • Prioritize:
    • continue/resume items
    • recently used domain surfaces
    • user-saved critical content
  • Abort/limit prefetch when offline, low battery, or constrained network.

UX and Product Rules#

  • Always show global online/offline state indicator in shell.
  • For stale fallback content, show freshness timestamp.
  • Provide explicit retry actions on failed fetch/sync.
  • Never silently drop user write actions.

Platform Implementation Guidance#

Mobile#

  • Use managed local stores (AsyncStorage/SQLite/file system) by data class.
  • Use queued sync for write actions and media download manager for offline media.
  • Persist sync queue across app restarts.

Web/PWA#

  • Use service worker strategies per matrix.
  • Use IndexedDB for offline data models and sync queues.
  • Use Background Sync where supported; fallback to foreground replay.

Existing Pattern Alignment#

  • Aligns with Tara web SW strategy for static/nav split.
  • Aligns with Veritas web sync-manager queue model.
  • Aligns with Nyx Workbox runtime caching patterns.
  • Aligns with Veritas mobile offline cache + queue + eviction pattern.

Implementation Plan#

Phase 1: Policy and Contracts#

  • Define libs/oshun/offline policy APIs and cache classes.
  • Define queue item schema and sync result taxonomy.
  • Define per-endpoint cache classification.

Phase 2: Shell Integration#

  • Integrate global offline status and retry UX in shell.
  • Integrate queue persistence and replay orchestration.
  • Integrate stale-data indicators for fallback reads.

Phase 3: Hardening#

  • Add cache budget enforcement and eviction diagnostics.
  • Add conflict resolution integration tests.
  • Add partial-outage and airplane-mode scenario tests.

Phase 4: Observability#

  • Emit offline/sync events for dashboarding.
  • Add alerts for queue growth, replay failures, and stale fallback spikes.

Success Metrics#

  • Core shell routes render with meaningful fallback in offline mode.
  • Queue replay success rate >= 98% after reconnection.
  • No silent write loss for queued operations.
  • Cache growth remains within configured budgets across target devices.
  • Offline-to-online recovery latency meets UX SLA.

Consequences#

Positive Consequences#

  • ✅ Stronger reliability for real-world network conditions.
  • ✅ Consistent offline behavior across mobile and web/PWA.
  • ✅ Explicit and testable policy for caching and sync.
  • ✅ Better trust via visible state/retry/fallback behavior.

Negative Consequences#

  • ❌ Higher implementation complexity (queue + conflict logic).
  • ❌ More QA permutations (network/state/storage combinations).
  • ❌ Ongoing tuning needed for cache and prefetch budgets.

Risks and Mitigations#

Risk Probability Impact Mitigation
Stale data shown too long Medium Medium TTL + staleness indicators + refresh triggers
Queue replay duplicates writes Medium High idempotency keys + server dedupe
Cache pressure on low-storage devices Medium Medium strict budgets + LRU + user cleanup controls
Offline logic drift across platforms Medium High shared policy contracts in libs/oshun/offline

Security and Compliance#

  • Do not cache sensitive auth/session responses.
  • Encrypt or protect sensitive local data where required by policy.
  • Respect user consent/privacy settings in offline telemetry collection.

Monitoring and Observability#

Track:

  • offline entry/exit events
  • cache hit/miss rates by data class
  • queue depth and replay outcomes
  • conflict resolution outcomes
  • fallback-render counts and stale age distributions
  • docs/adr/ADR-0014-oshun-web-and-pwa-strategy.md
  • docs/adr/ADR-0016-shared-identity-and-cross-domain-session-model.md

References#

  • apps/tara/web/public/sw.js
  • apps/veritas/web/public/sw.js
  • apps/veritas/web/src/lib/offline/sync-manager.ts
  • apps/nyx/mobile/vite.config.ts
  • apps/veritas/mobile/src/services/offline.ts
  • apps/tara/mobile/src/services/download.ts