Sales Diary - Offline-First Mobile Apps: Building for Rural Indonesia with React Native

Building an offline-first React Native app for rural Indonesia. Improved crash-free rates from 70% to 95% while handling zero connectivity scenarios

Role

Frontend Engineer

Associated With

eFishery - Enterprise Platform Team

Timeline

November 2020 - February 2022

Tools

React Native, PouchDB

Sales Diary - Offline-First Mobile Apps: Building for Rural Indonesia with React Native

Overview

Imagine building an app for users who might not have internet for days. That was the challenge with Sales Diary, an offline-first mobile app for 100+ field sales staff to record their activities, such as payment collection, record lead data for acquisition, and product order requests for fish/shrimp farmers in rural Indonesia, where connectivity is unreliable at best. The data collected is used for internal analytics and business development teams to help them generate higher sales conversion rates

I joined the team to help build the product to scale the app architecture and solve performance and reliability issues. This project became one of the most challenging works of my career, not just because of its unique case as a user-facing app, but because of the depth of the problems, ensuring it remains functional when accessed from rural areas

The result? Improved crash-free rates from 70% to 95% and enabled reliable data collection in areas with zero connectivity

Key Challenges

Offline Sync Architecture

The app needed to work without internet, sometimes in a very limited connectivity

I implemented:

  • Local-first data storage with SQLite
  • Conflict resolution by using vector clocks
  • Queue-based sync when connectivity returned
  • Exponential backoff for failed syncs

Preventing Duplicate Submissions

When connectivity spiked, users might tap "Submit" multiple times.

Solution: Draft system with Nano ID-based deduplication

Performance on Low-End Devices

Many field staff used entry-level Android devices

Optimizations:

  • Reduced bundle size by removing unnecessary libraries
  • Optimized list rendering with React Native's FlatList
  • Improving form validation for complex lead data by modularizing the form components with their own state management
  • Making the UI feel familiar, even though the design isn't good

How I Overcame Them

It was my initial experience developing an offline-first application, which must be dependable in rural areas that present unique obstacles, such as the need to record data when there is little to no internet connection. I had to learn on the fly about how the app saves data, syncing between remote and local data from the device, and how to deal with duplicate data that is being saved accidentally when the connection gets a spike

Improving the Functionality

I was asked to improve its lead acquisition feature, which is basically just a form input with so much data needing to be filled, but it lacks solid validation that leads the data collection not to be good enough for the data team to process

The other challenge was the UI, where it doesn't feel intuitive enough due to its UI design; it was translated from a low-fidelity wireframe, which confuses the user. Not only UI, but also its performance is not good enough, like it has untraceable errors and compatibility issues on some devices. But since it was developed pragmatically in the first place, I focused on its functionality and eventually improved its usability and ensured the app doesn't crash

I succeeded in improving the feature by implementing a better form validation, refactoring the code to colocate its state management that makes the code more readable, and preventing flaws on the UI that can make the user submit duplicate data

The Rewrite Decision

My lead had an idea to rewrite the app from scratch since it feels bloated; some of the concerns are that the code isn't maintainable, they wanted to use a UI library to have better visuals, and the legacy code was challenging to understand

Why we did it:

  • Technical debt made features tak longer to deliver
  • Crash reports were difficult to trace
  • No state management pattern (e.g. Redux, Context-Reducer)
  • Poor error handling

How I approached it:

  • Kept the rewrite parallel to the existing app (no downtime)
  • Migrated users gradually (20% → 50% → 100%)
  • Established coding standards and architecture patterns
  • Implemented comprehensive error logging with Sentry

The payoff:

95%+ crash-free rate, faster feature delivery, and maintainable codebase for the team

Technical Stack

Legacy Version:

  • React Native (untyped JavaScript)
  • No state management, relies on React built-in useState hooks
  • Basic error handling
  • No UI design, purely from lo-fi wireframe

Rewrite Version:

  • React Native + TypeScript
  • Context-Reducer pattern for forms
  • Sentry for error tracking
  • Better UI components with design system

What I Learned

Sales Diary taught me how to make a reliable app when there is little or no internet connection and also think about its performance, especially on various devices that the field sales have. It was a unique real-world problem that I might not think about, and I had to think about trust, empathy, and scale all at once. I learned how to build an app with scalable architecture, the value of designing for performance, aligning with the product team and the users, and understanding the pain points from the users by reaching them directly to ensure its usability