PowerSync React Native Background Syncing


To ensure your app can sync changes in the background using PowerSync, you'll need a few essential dependencies provided by Expo:
expo-background-fetch
(for SDKs below 53) orexpo-background-task
(for SDK 53 and above)expo-task-manager
These libraries allow you to run background tasks periodically, even when your app is not active.
To install them, run the following command:
bunx expo install expo-background-task expo-task-manager
Platform differences
Android
On Android, the WorkManager
API allows specifying a minimum interval for a task to run (minimum 15 minutes). The task will execute sometime after the interval has passed, provided the specified conditions are met.
iOS
On iOS, the BGTaskcheduler
API decides the best time to launch your background task. The system will consider the battery level, the network availability, and the user's usage patterns to determine when to run the task. You can still specify a minimum interval for the task to run, but the system may choose to run the task at a later time.
Then we can create a separate file called BackgroundSyncTask.ts, where we will define our task.
TaskManager.defineTask(BACKGROUND_SYNC_TASK, async () => {
try {
// Step 1: Validate your tokens first for powersync
// Step 2: Connect to powersync instance
const connector = new Connector(token);
await powersync.connect(connector, {
params,
});
//Step 3: Perform any logic you want to here, powersync will automatically handle syncing and uploading
drizzleDB.insert().into(anyTable)
//You can also register a listener here as well
await new Promise((resolve) => {
const unregister = powersyncAuth.registerListener({
statusChanged: (status) => {
const hasSynced = Boolean(
status.lastSyncedAt
);
const downloading = status.dataFlow?.downloading || false;
const uploading = status.dataFlow?.uploading || false;
console.log(
'[PowerSync] Status changed:',
hasSynced ? 'β
Synced' : 'β³ Not yet synced',
downloading ? 'π₯ Downloading' : 'β
Not downloading',
uploading ? 'π€ Uploading' : 'β
Not uploading'
);
// You can track download progress here if needed
// e.g., status.dataFlow?.downloadProgress
// Resolve only when initial sync is complete
if (hasSynced && !uploading) {
console.log('[PowerSync] Sync complete β
');
resolve();
unregister();
}
},
});
});
return BackgroundTask.BackgroundTaskResult.Success;
} catch (error) {
console.error('β Background sync task failed:', error);
return BackgroundTask.BackgroundTaskResult.Failed;
}
});
PowerSync automatically syncs the new changes, no need to invoke its uploadData function
HEADS UP: if you are stuck at this error
[PowerSyncStream]', 'Could not apply checkpoint due to local data. Waiting for in-progress upload before retrying.'
In your uploadData
function, if you're using the native fetch()
API, keep in mind that it may not work reliably in the background. To improve stability, consider switching to a library like axios
, which offers better handling of timeouts, retries, and error states.
After ensuring your upload logic is solid, enhance your background task by adding checks like:
β Is the task registered?
β Is the device connected to the network?
Once that's done, make sure to register your task at the top level of your app β for example, in your index.ts
or main layout file:
async function registerBackgroundTaskAsync() {
return BackgroundTask.registerTaskAsync(BACKGROUND_TASK_IDENTIFIER);
}
And thatβs it β you now have a working background sync task using PowerSync in your React Native + Expo app. π This setup ensures your app remains consistent and up-to-date, even when running in the background.
To test and debug the task on your android device you can follow these instructions on expo docs
Subscribe to my newsletter
Read articles from Fahad Rizwan directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
