Skip to main content

Philosophy

New Expensify is designed to work perfectly offline. Users can perform almost any action without an internet connection, and those actions are automatically synchronized when connectivity is restored.
Core Principle: Allow users to do as much as possible when offline. Assume most requests will succeed and proceed optimistically.

Offline UX Patterns

Every feature in New Expensify follows one of these offline patterns:

Pattern A: Optimistic Without Feedback

When to use: The user needs instant feedback but doesn’t need to know when the server confirms the change. Example: Pinning a chat
Implementation:
  • Use API.write()
  • Only provide optimisticData
  • UI updates immediately
  • No loading indicators needed

Pattern B: Optimistic WITH Feedback

When to use: The user needs to know that data is pending server confirmation. Example: Sending a chat message
Implementation:
  • Use API.write()
  • Include optimisticData, successData, and failureData
  • Add pendingAction to show pending state
  • Wrap UI in OfflineWithFeedback component
UI Component:
Visual Feedback:
  • Adding: Item shown at 50% opacity when offline
  • Updating: Item shown at 50% opacity when offline
  • Deleting: Item shown with strikethrough when offline
  • Error: Item shown with red error message and dismiss button

Pattern C: Blocking Form

When to use:
  • Form requires server validation
  • Server response is unpredictable
  • Moving money or other critical operations
Example: Inviting workspace members
Implementation:
  • Use FormAlertWithSubmitButton
  • Set enabledWhenOffline={false}
  • Users can fill out form offline, but can’t submit
  • Data is saved locally via form draft

Pattern D: Full Page Blocking

When to use:
  • READ request where stale data is unacceptable
  • Data must be fetched from server before display
  • Only use as last resort
Example: Loading bank accounts from Plaid
Implementation:
  • Wrap component in FullPageOfflineBlockingView
  • Only show when offline AND data is not available
  • Provide clear instructions to user

Pattern None: No Offline Behavior

When to use:
  • No server interaction
  • OR data is READ and stale data is acceptable
Example: About page with static content
Implementation:
  • Use API.read() for server data
  • No special offline handling
  • Shows stale data until fresh data loads

Choosing the Right Pattern

Request Queue

How It Works

WRITE requests are queued and replayed when online:
  1. User performs action while offline
  2. API.write() creates request with optimistic data
  3. Request is persisted to disk (via Onyx)
  4. Optimistic data is applied immediately
  5. Request waits in queue
  6. When online, queue processes requests in order
  7. Success/failure data is applied based on response

Sequential Queue

Requests are processed sequentially to maintain order:

Viewing the Queue

During development:

Conflict Resolution

What Are Conflicts?

Conflicts occur when:
  • User makes changes offline on Device A
  • User makes different changes online on Device B
  • Device A comes online and tries to sync

Built-In Strategies

1. Last Write Wins

Default behavior - the most recent change is kept:

2. Duplicate Detection

Prevents duplicate requests:

3. Custom Conflict Resolution

Network Detection

Using Network State

Subscribing to Network Changes

Error Handling

Displaying Errors

Use the Red Brick Road (RBR) pattern to guide users to errors:

Clearing Errors

Retry Logic

Failed requests are automatically retried:

Pending States

Pending Actions

Field-Level Pending States

For partial updates:

Testing Offline Behavior

Simulating Offline Mode

Testing Optimistic Updates

Best Practices

1. Always Provide Optimistic Data

2. Handle Failures Gracefully

3. Use Appropriate Patterns

Choose the right offline pattern for your use case (see flowchart above).

4. Test Offline Scenarios

Always test:
  • Action performed offline
  • Action performed online
  • Error scenarios
  • Network changes during action

5. Provide Clear Feedback

Use OfflineWithFeedback to show pending states visually.

Common Pitfalls

1. Not Providing Failure Data

2. Blocking When Not Necessary

3. Not Handling Errors

Performance Considerations

Batch API Calls

Group related updates:

Optimize Onyx Updates

Next Steps

State Management

Learn more about Onyx

API Reference

Understand API patterns

Testing

Test offline behavior

Best Practices

Follow offline-first best practices