Mobile Background Work and Battery Limits
On a phone, battery life is the operating system's top priority, and background apps are the biggest threat to it. Both Android and iOS therefore restrict what apps can do when they are not on screen: they delay work, batch it, suspend processes, and kill them when memory is needed. Code that assumes a background timer will fire on schedule, a service will keep running, or a sync will finish before the user closes the app works on the developer's phone on a charger and fails for real users.
Reliable background work cooperates with the platform. Use the scheduling APIs the OS provides, describe the constraints your work needs, make every task idempotent and resumable so delays and interruptions are harmless, and keep work that truly must run now — a navigation session, a user-started upload — in the explicit modes designed for it.
TL;DR
- Assume background work will be delayed, batched, interrupted, or skipped; design it to be idempotent and resumable.
- Android: use WorkManager for deferrable, guaranteed work with constraints; foreground services (with declared types) only for user-visible ongoing tasks.
- Android's Doze, App Standby Buckets, and background execution limits delay work; exact alarms require special permission.
- iOS suspends apps shortly after backgrounding; use BGTaskScheduler for refresh and processing tasks and background URL sessions for transfers.
- Silent push is throttled and not guaranteed on both platforms; high-priority pushes are for user-visible notifications.
- Handle process death, revoked permissions, and OEM battery savers, and measure what actually runs in the field.
Quick Example
A periodic sync on Android with WorkManager, constraints, and retries:
A background refresh task on iOS (the identifier must also be listed under BGTaskSchedulerPermittedIdentifiers in Info.plist):
Core Concepts
Android Power Management
WorkManager is the recommended API for persistent work: it survives app restarts and reboots, respects constraints (network, charging, battery, storage), supports chaining and unique work, and uses the right system scheduler underneath. Expedited work runs important short tasks promptly, subject to quotas. Many manufacturers add their own aggressive battery savers on top of these rules, which kill apps or delay work further.
iOS Background Execution
earliestBeginDate is only a lower bound: the system decides when — or whether — to run refresh tasks, favoring apps the user opens often.
Push Messages
Use push to tell the user something (visible notifications) or to hint that new data exists. Do not rely on silent or data-only messages for correctness: both platforms limit them, and on Android, high-priority messages that do not lead to user-visible notifications can be deprioritized. See Push Notifications.
Designing Robust Background Work
- Idempotent: running a sync twice must not duplicate data; use idempotency keys for server writes. See Idempotency.
- Resumable: record progress (cursor, uploaded parts) so interrupted work continues instead of restarting.
- Bounded: finish within the time the system gives, check for cancellation, and split large jobs.
- Constraint-aware: defer heavy work to unmetered networks and charging when possible.
- Permission-aware: users revoke location, notifications, or background refresh at any time; check before work and degrade gracefully.
- Foreground-first: do important work when the app is open, and use background work to catch up.
Kotlin coroutines in workers and Swift structured concurrency both propagate cancellation; honor it so the system's expiration handlers can stop work cleanly. See Kotlin Coroutines and Structured Concurrency.
Measuring What Really Runs
Background behavior varies by device, OS version, manufacturer, and user habits. Log when work is scheduled, started, completed, and expired — with device model and OS version — and watch sync freshness and failure rates. Test with tools that force idle states: adb shell dumpsys deviceidle force-idle for Doze, adb shell am set-standby-bucket for buckets, and Xcode's debugger commands for launching background tasks.
Best Practices
Use the Platform Scheduler
WorkManager and BGTaskScheduler know about battery, network, and usage patterns; custom timers and long-running services fight them and lose.
Make Every Task Safe to Repeat
Assume tasks run late, run twice, or stop halfway, and design storage and server APIs accordingly.
Reserve Foreground Services for Visible Work
Use them only for work the user is aware of and expects to continue, with an accurate notification and service type.
Instrument Background Work
Measure execution in the field instead of trusting behavior on development devices.
Common Mistakes
Timers in the Background
Relying on Silent Push for Data Correctness
Non-Idempotent Retries
FAQ
What is the best way to run background work on Android?
WorkManager for deferrable work that must eventually complete, with constraints and retries. Use a foreground service with a declared type only for ongoing, user-visible work such as navigation or media playback.
How do I run code periodically on iOS?
Register a BGAppRefreshTask with BGTaskScheduler and schedule it with an earliest begin date. The system decides when to run it based on usage, battery, and network conditions, so it is not a precise timer.
Why doesn't my background task run on schedule?
Power management delays or skips work: Doze and standby buckets on Android, usage-based scheduling on iOS, low-power modes, manufacturer battery savers, and user settings all affect execution.
Can I keep my app running in the background?
Only for specific, user-visible use cases such as audio playback, navigation, calls, or ongoing user-initiated tasks, using the dedicated platform modes. General-purpose apps are suspended or limited.
Is silent push reliable?
No. Both platforms throttle background push, and some states — such as a user force-quitting an app on iOS — prevent delivery. Use it as a hint, not a guarantee.
Related Topics
- Mobile Development — Building apps for phones and tablets
- Android Development — Android platform development
- iOS Development — Apple platform development
- Push Notifications — Notifications and background messages
- Kotlin Coroutines and Structured Concurrency — Cancellation-aware async code
- Idempotency — Making repeated work safe