Skip to content
Innovialabs

Background Work on iOS and Android: Limits and Reliable Patterns

Advanced4 min

In short

Neither OS guarantees exact timing for background work, so reliable sync relies on system schedulers, OS-managed background transfers, idempotent operations and a catch-up sync every time the app opens.

The key point: background time is not guaranteed

Both iOS and Android protect battery life, so the OS decides when and how long your app may run in the background. You cannot count on code running "every 15 minutes" or "at exactly 9:00". The reliable approach treats background time as a bonus:

  • schedule work through system schedulers (WorkManager, BGTaskScheduler);
  • use background network sessions managed by the OS for file transfers;
  • make operations idempotent and resumable;
  • always catch up on sync when the app opens.

Android limits

  • Doze: when the device is stationary with the screen off, the system defers network access, alarms and jobs to short maintenance windows.
  • App Standby Buckets: the less often a user opens your app, the less background time it gets.
  • Background service restrictions: a regular background Service does not live long; long user-visible work needs a foreground service with a notification and a declared type.
  • Manufacturer layers: some OEMs ship their own aggressive battery optimizers that kill processes more than stock Android does. On those devices you may need to ask users to exempt the app.

iOS limits

  • Once backgrounded, an app is suspended quickly. You can request extra time to finish a short task, but that means minutes, not hours.
  • BGTaskScheduler runs BGAppRefreshTask (short refresh) and BGProcessingTask (longer work, often while charging). The system picks the time, based partly on how often the user opens the app.
  • A silent push (content-available) can wake the app, but delivery is not guaranteed and is throttled.
  • If the user force-quits the app by swiping it away, most background mechanisms stop waking it.

Which tool for which job

JobAndroidiOS
Periodic syncWorkManager, PeriodicWorkRequestBGAppRefreshTask
Heavy processing, backupWorkManager with constraints (charging, Wi-Fi)BGProcessingTask
File upload and downloadWorkManager, foreground service if neededBackground URLSession
Urgent server eventPush notification (FCM)Push notification (APNs)
Route tracking, navigationForeground service of type locationBackground location mode
Geofence-based updatesGeofencing APIRegion monitoring, significant location changes

WorkManager in practice

WorkManager survives device reboots and picks the right mechanism under the hood:

val request = PeriodicWorkRequestBuilder<SyncWorker>(1, TimeUnit.HOURS)
    .setConstraints(
        Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()
    )
    .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 30, TimeUnit.SECONDS)
    .build()

WorkManager.getInstance(context).enqueueUniquePeriodicWork(
    "sync", ExistingPeriodicWorkPolicy.KEEP, request
)

A unique work name prevents duplicates on every app launch. The system enforces a minimum interval for periodic work, and the actual run time can drift.

Background location and uploads

  • Background location requires a separate permission, a clear explanation to the user and a justification in store review. Use the lowest accuracy that works: significant location changes and geofences use far less battery than continuous GPS.
  • Large uploads should be handed to the OS: on iOS, a background URLSession keeps transferring even while the app is suspended; on Android, WorkManager with resume support. The server must support resumable, chunked uploads.

Patterns for reliable sync

  1. Local operation queue. User actions are written to an on-device database first, then sent.
  2. Idempotency. Each operation has a unique key, so a retry never creates a duplicate on the server.
  3. Incremental sync by cursor or timestamp instead of reloading everything.
  4. Retries with exponential backoff that respect network state.
  5. Push as a signal, not as data: the notification says "something changed" and the app fetches the data itself.
  6. Sync on app open as a mandatory safety net.
  7. Monitoring: log when jobs actually ran so you can spot problems on specific devices.

FAQ

Not reliably. For reminders to the user, use local notifications, and sync data at the next opportunity the system gives you.

We can help with this

If you'd rather get the result than figure it all out yourself — this is what we do every day.

Discuss a project

Read next

Have an idea or a task? Tell us about it

We'll reply within one business day and propose a solution. The consultation is free.