Software Engineering & Digital Products for Global Enterprises since 2006
CMMi Level 3SOC 2ISO 27001
View all services
Staff Augmentation
Embed senior engineers in your team within weeks.
Dedicated Teams
A ring-fenced squad with PM, leads, and engineers.
Build-Operate-Transfer
We hire, run, and transfer the team to you.
Contract-to-Hire
Try the talent. Convert when you're ready.
ForceHQ
Skill testing, interviews and ranking — powered by AI.
RoboRingo
Build, deploy and monitor voice agents without code.
MailGovern
Policy, retention and compliance for enterprise email.
Vishing
Test and train staff against AI-driven voice attacks.
CyberForceHQ
Continuous, adaptive security training for every team.
IDS Load Balancer
Built for Multi Instance InDesign Server, to distribute jobs.
AutoVAPT.ai
AI agent for continuous, automated vulnerability and penetration testing.
Salesforce + InDesign Connector
Bridge Salesforce data into InDesign to design print catalogues at scale.
View all solutions
Banking, Financial Services & Insurance
Cloud, digital and legacy modernisation across financial entities.
Healthcare
Clinical platforms, patient engagement, and connected medical devices.
Pharma & Life Sciences
Trial systems, regulatory data, and field-force enablement.
Professional Services & Education
Workflow automation, learning platforms, and consulting tooling.
Media & Entertainment
AI video processing, OTT platforms, and content workflows.
Technology & SaaS
Product engineering, integrations, and scale for tech companies.
Retail & eCommerce
Shopify, print catalogues, web-to-print, and order automation.
View all industries
Blog
Engineering notes, opinions, and field reports.
Case Studies
How clients shipped — outcomes, stack, lessons.
White Papers
Deep-dives on AI, talent models, and platforms.
Portfolio
Selected work across industries.
View all resources
About Us
Who we are, our story, and what drives us.
Co-Innovation
How we partner to build new products together.
Careers
Open roles and what it's like to work here.
News
Press, announcements, and industry updates.
Leadership
The people steering MetaDesign.
Locations
Gurugram, Brisbane, Detroit and beyond.
Contact Us
Talk to sales, hiring, or partnerships.
Request TalentStart a Project
Mobile Development

Implementing Offline Functionality in React Native Apps

GS
Girish Sagar
Technical Content Lead
December 22, 2024
10 min read
Implementing Offline Functionality in React Native Apps — Mobile Development | MetaDesign Solutions

Why Offline-First Architecture Is Essential for Mobile Apps

Mobile users spend a significant portion of their time in areas with poor or no connectivity—subways, elevators, airplanes, rural regions, and buildings with weak signals. An app that shows a blank screen or a generic error when the network drops provides a fundamentally broken user experience. Offline-first architecture designs the app to work locally by default, treating network connectivity as an enhancement rather than a requirement. Data is stored locally, user actions are queued, and synchronization happens seamlessly when connectivity is restored. This approach dramatically improves perceived performance (local reads are instant) and reliability.

AsyncStorage: Simple Key-Value Persistence

AsyncStorage (from `@react-native-async-storage/async-storage`) provides a simple, unencrypted, asynchronous key-value store. It is ideal for persisting user preferences, authentication tokens, small JSON objects, and cached API responses. Use `await AsyncStorage.setItem('user_settings', JSON.stringify(settings))` to save and `JSON.parse(await AsyncStorage.getItem('user_settings'))` to retrieve. AsyncStorage has practical size limits (6MB on Android by default) and is not suitable for large datasets, complex queries, or structured relational data. For those needs, use a proper database.

SQLite: Structured Relational Data on Device

For apps that need to query structured data offline—filtering, sorting, joining tables, full-text searchSQLite via `react-native-sqlite-storage` or `expo-sqlite` is the right choice. SQLite provides a full SQL engine running locally on the device. Create tables, insert records, and execute complex queries with joins, aggregations, and indexes. A field service app, for example, can store thousands of work orders with customer details, parts lists, and completion statuses, allowing technicians to search and update records entirely offline. SQLite databases can grow to gigabytes without performance issues, making them suitable for data-intensive applications.

Realm: High-Performance Object Database with Live Objects

Realm (now part of MongoDB Atlas Device SDK) is an object-oriented mobile database designed for React Native. Unlike SQLite's SQL interface, Realm uses a native object API: define a schema class, then query with `realm.objects('Task').filtered('status == "pending"').sorted('dueDate')`. Realm's killer feature is live objects—any query result automatically updates in real-time when underlying data changes, eliminating manual state management. Combined with Atlas Device Sync, Realm provides automatic bidirectional sync between the device and MongoDB Atlas, handling conflict resolution, network partitions, and retry logic out of the box.

Detecting Connectivity with @react-native-community/netinfo

Accurate network detection is the foundation of offline-aware UX. Use `@react-native-community/netinfo` to subscribe to connectivity changes: `const unsubscribe = NetInfo.addEventListener(state => { setIsConnected(state.isConnected); setConnectionType(state.type); })`. The library provides not just a boolean connected/disconnected state, but the connection type (wifi, cellular, ethernet) and whether the connection is actually reachable (a device can be connected to WiFi that has no internet access). Use this information to display contextual UI: a subtle offline banner, a "changes will sync when online" message, or a full offline mode indicator.

Transform Your Publishing Workflow

Our experts can help you build scalable, API-driven publishing systems tailored to your business.

Book a free consultation

Data Synchronization Strategies and Conflict Resolution

The most complex challenge in offline-first apps is synchronizing data when connectivity resumes. Queue user actions locally using an operations log pattern: each create/update/delete action is stored as a timestamped operation in a local queue. When online, replay the queue sequentially against the server. For conflict resolution, implement one of three strategies: Last-Write-Wins (simplest—timestamp-based), Server-Wins (server state always takes precedence), or Merge (field-level conflict resolution using operational transforms). Use the stale-while-revalidate pattern for reads: serve cached data immediately while fetching fresh data in the background, then update the UI when the response arrives.

Optimistic UI Updates for Instant Feedback

Optimistic UI updates apply user actions to the local state immediately, before server confirmation. When a user marks a task as complete, the checkbox animates instantly and the task moves to the "completed" section—the server request happens asynchronously in the background. If the server request fails, the UI rolls back the change and shows an error notification. This pattern makes the app feel instantaneous regardless of network conditions. Implement with a state management library like Zustand or Redux, maintaining both a "committed" state (server-confirmed) and an "optimistic" state (locally applied), and reconciling them when the server responds.

Security, Encryption, and Offline Testing

Data stored on device must be protected. Encrypt sensitive data using `react-native-keychain` for credentials and tokens, and `realm.open({ encryptionKey })` for encrypted Realm databases. Never store raw API keys, passwords, or PII in AsyncStorage without encryption. For testing offline scenarios, use Airplane Mode toggling on physical devices, the Network Link Conditioner on iOS Simulator, and Android Emulator's network throttling to simulate various connectivity conditions. Write integration tests that verify: the app renders cached data when offline, user actions are queued correctly, and synchronization completes successfully when connectivity is restored.

FAQ

Frequently Asked Questions

Common questions about this topic, answered by our engineering team.

AsyncStorage for simple key-value pairs (settings, tokens). SQLite for structured relational data requiring complex queries, joins, and indexes. Realm for object-oriented data with live queries and optional cloud sync via MongoDB Atlas Device Sync. Choose based on your data complexity and query needs.

Use @react-native-community/netinfo with NetInfo.addEventListener() to subscribe to connectivity changes. It provides connection type (wifi, cellular), reachability status, and whether the device actually has internet access (not just a WiFi connection).

Use an operations log pattern: queue each user action (create/update/delete) locally with a timestamp. When online, replay the queue against the server. For conflict resolution, choose Last-Write-Wins (simplest), Server-Wins, or field-level Merge based on your data sensitivity requirements.

Optimistic UI applies user actions to local state immediately, before server confirmation. The user sees instant feedback regardless of network speed. If the server request fails, the UI rolls back the change. This makes the app feel responsive even on slow or intermittent connections.

Use react-native-keychain for credentials and tokens. Enable Realm database encryption with an encryption key. Never store sensitive data in plain AsyncStorage. Encrypt all PII and API keys stored on device to prevent unauthorized access if the device is compromised.

Discussion

Join the Conversation

Ready when you are

Let's build something great together.

A 30-minute call with a principal engineer. We'll listen, sketch, and tell you whether we're the right partner — even if the answer is no.

Talk to a strategist
Need help with your project? Let's talk.
Book a call