How background tasks work in Capacitor
What Capacitor apps can and cannot do in the background on iOS and Android, how to run background fetch and tasks within OS limits, and how to check for an OTA update on resume.
“Can my Capacitor app do work in the background?” has a nuanced answer: yes, but far less freely than you'd hope, because iOS and Android both aggressively limit background execution to protect battery. This guide explains what's actually possible, how to run background fetch and short tasks within the OS rules, and how to check for an OTA update at the right moments.
Reset your expectations first: mobile background execution is not a server. You get brief, OS-scheduled windows — not a long-running loop. Design for “do a little, quickly, when the OS lets me,” not “run continuously.”
What the platforms allow
- Background fetch — periodic, OS-scheduled wake-ups to refresh data. Frequency is the OS's call, not yours.
- Finish-on-suspend tasks — a short window to complete work when the app goes to the background (an upload, a save).
- Push-triggered work — a silent push can wake the app to do a small task.
Anything resembling a persistent background service will be throttled or killed. Build around the windows the OS gives you.
Running a background task
Use a Capacitor background-task/runner plugin to register work and signal completion so the OS knows you're done and can suspend you cleanly:
// on app pause, finish critical work in the granted window
App.addListener('pause', async () => {
const taskId = await BackgroundTask.beforeExit(async () => {
await flushPendingUploads();
BackgroundTask.finish({ taskId });
});
});Check for updates on resume
A natural place to check for an OTA update is when the app returns to the foreground — the user is about to interact anyway. Trigger a check on resume so an available bundle is ready by the time they need it:
import { OtaKit } from '@otakit/capacitor-plugin';
App.addListener('resume', () => {
OtaKit.check();
});See Events and background vs foreground updates for how this ties into your update UX.
Test background behavior on real devices with battery optimization enabled — the emulator is far more permissive than a real phone in low-power mode, so “works in the emulator” means little here.
Where to go next
See Plugin API for check() and the update lifecycle, and offline support for handling the no-network case.