Does Capacitor's BackgroundTask plugin preserve retry markers after process termination?
0 reputation · 31 May 2022, 00:22 UTC
0 reputation · 31 May 2022, 00:22 UTC
I'm designing a retry mechanism for a Capacitor app that performs server writes through the @capacitor-community/http plugin. Before each write, I persist a unique operation marker using the Capacitor Storage API, and on retry I check that marker to avoid executing the same write twice. This works while the app stays alive.
The unresolved case is process termination: if the app is killed (or suspended by Android battery optimizations) while a retry is pending in a BackgroundTask, I cannot tell whether the Storage marker is guaranteed to have been flushed before the task is suspended, or whether the retry queue state survives a cold restart. If the marker is lost, the app could either skip a legitimate retry or issue a duplicate write on the next launch.
Assume Capacitor 6 with the official Storage and BackgroundTask plugins on Android and iOS.
Is the Storage write guaranteed to be durable before a BackgroundTask is suspended or the process is killed? What is the recommended pattern for reconciling a persisted retry marker against server state after a cold restart? Should deduplication rely on the client marker at all, or must the idempotency key be enforced entirely server-side?
34775 reputation · 31 May 2022, 02:26 UTC
No, the BackgroundTask plugin does not preserve retry markers or queue states after process termination. It provides a temporary execution window to finish a current operation; it is not a persistent job scheduler. If the OS kills the process or the background window expires, any pending logic in the JavaScript heap is lost.
While the Capacitor Storage (Preferences) plugin utilizes native durable stores (SharedPreferences on Android and UserDefaults on iOS), there is no transactional guarantee that a write is physically flushed to disk before an abrupt process termination. Because the bridge between the JavaScript engine and the native layer is asynchronous, a process kill occurring immediately after a Storage.set() call may result in the marker never reaching the native disk layer.
Since client-side markers cannot guarantee exactly-once delivery across cold restarts, you should shift the source of truth to the server. The recommended pattern is as follows:
X-Idempotency-Key) with the server write.To verify the failure point in your specific environment, use the following scoped test:
BackgroundTask and initiate a Storage.set().Diagnostic Detail Needed: Are you using the @capacitor/preferences plugin or a custom SQLite implementation? SQLite provides stronger ACID guarantees for markers than the key-value Preferences API.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.