BBMM Technologies
← All articles
7 min readios, background-tasks, battery, scheduling

Battery-Aware Background Scheduling on iOS

By Mykhailo Boichuk · Co-founder & Vice-President

In short

iOS does not let apps run freely in the background; it schedules deferred work to protect battery and performance, choosing when to run based on charging state, network, and user behavior. Building battery-aware background scheduling means using the system’s task APIs, declaring work as deferrable, keeping each run short, and accepting that the system, not the app, decides timing.

The system owns the schedule

On iOS, an app does not get to decide when its background work runs. The operating system does, and it makes that decision in service of battery life, thermal limits, and overall responsiveness. An app that assumes it can run on a fixed interval in the background will find its work delayed, coalesced, or skipped. The first adjustment is to accept that background execution is a privilege granted by the system, not a guarantee.

This is a deliberate design. Uncontrolled background activity is one of the largest drains on a phone’s battery, so the platform constrains it heavily. Working with these constraints, rather than against them, is what gets background work to run reliably.

Declare work as deferrable

iOS provides task-scheduling APIs for background work, distinguishing short refresh tasks from longer processing tasks. The app registers the kind of work it wants to do and submits a request; the system then schedules it at a time it judges appropriate, often when the device is charging, on Wi-Fi, and not in active use.

  • Use the background-task APIs rather than trying to keep the app running.
  • Distinguish brief refresh work from longer maintenance work and request the appropriate type.
  • Treat scheduling as a hint; the system decides the actual time of execution.
  • Always provide an expiration handler so work can stop cleanly when the system reclaims time.

Be a good citizen of the battery

The system learns from how an app behaves. Work that finishes quickly, respects its time limit, and does not waste energy is more likely to be scheduled again promptly. Work that overruns or drains power tends to be granted less time. Designing each background run to be short and efficient is therefore not only courteous but self-interested.

Each background run should do the minimum useful unit of work and exit. Long-running or open-ended background tasks are the wrong model on iOS; break the work into small pieces that can complete within the time the system allows.

Design for uncertainty in timing

Because the system controls timing, an app cannot rely on background work happening at a precise moment. Logic that assumes a refresh ran exactly on schedule will break. The robust approach is to design features that degrade gracefully when background work is delayed, refreshing on next launch if a background refresh did not occur, and never depending on background execution for correctness.

The combination is straightforward to state and important to follow: ask the system politely for time through the proper APIs, do small efficient units of work when granted it, and never assume the work ran. An app built this way conserves battery, satisfies the platform, and still keeps its data reasonably fresh.

Key takeaways

  • iOS decides when background work runs, prioritizing battery life and performance.
  • Use the background-task APIs and declare work as deferrable rather than trying to stay running.
  • Keep each background run short and efficient so the system continues to grant time.
  • Always handle task expiration so work stops cleanly when time is reclaimed.
  • Design features to degrade gracefully when background execution is delayed or skipped.

Frequently asked questions

Can an iOS app run continuously in the background?
No. The system schedules deferred background work to protect battery and performance, and an app must use the background-task APIs and accept that the system controls when its work runs.
Why does my background task not run when expected?
Because iOS chooses the timing based on factors like charging state, network, and usage. Scheduling is a hint, not a guarantee, so tasks may be delayed, coalesced, or skipped.
How do I make background work reliable?
Keep each run short and efficient, handle expiration cleanly, and design features to degrade gracefully and refresh on next launch if a background run did not happen.

References

About the author

Mykhailo Boichuk

Co-founder & Vice-President

Mykhailo is an engineer who builds native applications and the systems behind them. He concentrates on macOS and iOS performance, local-first data architecture, and the synchronization problems that come with offline-capable software.