Data sync does not block UI thread
Why it matters
Running sync operations synchronously on the JavaScript thread blocks the event loop, freezing animations, touch responses, and navigation during large data transfers. ISO 25010:2011 performance-efficiency.time-behaviour requires that background operations do not degrade foreground frame rate. A frozen UI during sync is indistinguishable from a crash for the user — they force-quit the app, potentially interrupting the sync and corrupting queue state. Sync must be non-blocking even when processing hundreds of queued records.
Severity rationale
Medium because UI freezes degrade perceived reliability and can interrupt sync mid-flight, but the defect does not expose data or enable exploitation.
Remediation
Move heavy sync work to a background task using react-native-background-fetch or Expo's TaskManager. For foreground sync, ensure every I/O operation uses async/await and never calls synchronous storage APIs.
// npm install react-native-background-fetch
import BackgroundFetch from 'react-native-background-fetch';
export function registerBackgroundSync() {
BackgroundFetch.configure(
{ minimumFetchInterval: 15, stopOnTerminate: false, startOnBoot: true },
async (taskId) => {
try {
await drainQueue(executeAction);
await fetchRemoteUpdates();
} finally {
BackgroundFetch.finish(taskId);
}
},
(err) => console.error('BackgroundFetch failed to start:', err)
);
}
For in-app sync, never use AsyncStorage.getItemSync or equivalent; every call must be awaited. Wrap sync triggers in a debounce so rapid reconnect/disconnect cycles don't spawn concurrent sync runs.
Detection
-
ID:
non-blocking-sync -
Severity:
medium -
What to look for: Examine how data syncing is implemented. Look for use of background tasks, web workers, or non-blocking async patterns. Check that sync operations don't freeze the UI.
-
Pass criteria: Count all sync operation call sites. Sync operations run asynchronously (using async/await or Promise patterns) without blocking the main UI thread. App remains interactive during sync. At least 1 sync function uses non-blocking async patterns.
-
Fail criteria: Sync operations run synchronously on the main thread and freeze the UI during large data transfers.
-
Skip (N/A) when: Never — non-blocking sync is essential for user experience.
-
Detail on fail:
"Data sync runs on main thread. App freezes for 3-5 seconds during sync, making UI unresponsive." -
Remediation: Use background task scheduling:
// Install: npm install react-native-background-fetch import BackgroundFetch from 'react-native-background-fetch'; BackgroundFetch.configure( { minimumFetchInterval: 15, // minutes stopOnTerminate: false, startOnBoot: true, }, async (taskId) => { console.log('Background sync task:', taskId); try { await processQueue(); await syncData(); BackgroundFetch.finish(taskId); } catch (error) { console.error('Background sync failed:', error); BackgroundFetch.finish(taskId); } }, (error) => { console.error('BackgroundFetch error:', error); } );
External references
- iso-25010:2011 · performance-efficiency.time-behaviour — Time Behaviour
Taxons
History
- 2026-04-18·v1.0.0·Initial import from mobile-offline-storage·automated