iOS Background Execution Limits

This thread has been locked by a moderator.

I regularly see questions, both here on DevForums and in my Day Job™ at DTS, that are caused by a fundamental misunderstanding of how background execution works on iOS. These come in many different variants, for example:

  • How do I keep my app running continuously in the background?

  • If I schedule a timer, how do I get it to fire when the screen is locked?

  • How do I run code in the background every 15 minutes?

  • How do I set up a network server that runs in the background?

  • How can my app provide an IPC service to another one of my apps while it’s in the background?

  • How can I resume my app in the background if it’s been ‘force quit’ by the user?

The short answer to all of these is You can’t. iOS puts strict limits on background execution. Its default behaviour is to suspend your app shortly after the user has moved it to the background; this suspension prevents the process from running any code.

There’s no general-purpose mechanism for:

  • Running code continuously in the background

  • Running code at some specific time in the background

  • Running code periodically at a guaranteed interval

  • Resuming in the background in response to a network or IPC request

However, iOS does provide a wide range of special-purpose mechanisms for accomplishing specific user goals. For example:

  • If you’re building a music player, use the audio background mode to continue playing after the user has moved your app to the background.

  • If you’re building a timer app, use a local notification to notify the user when your timer has expired.

  • If you’re building a video player app, use AVFoundation’s download support.

Keep in mind that the above is just a short list of examples. There are many other special-purpose background execution mechanisms, so you should search the documentation for something appropriate to your needs.

IMPORTANT Each of these mechanisms fulfils a specific purpose. Do not attempt to use them for some other purpose. Before using a background API, read clause 2.5.4 of the App Review Guidelines.

Additionally, iOS provides some general-purpose mechanisms for background execution:

All of these mechanisms prevent you from abusing them to run arbitrary code in the background. As an example, consider the NSURLSession resume rate limiter.

For more information about these limitations, and background execution in general, I strongly recommend that you watch WWDC 2020 Session 10063 Background execution demystified. It’s an excellent resource.

Specifically, this talk addresses a common misconception about the app refresh mechanism (BGAppRefreshTaskRequest and the older background fetch API). Folks assume that app refresh will provide regular background execution time. That’s not the case. The system applies a range of heuristics to decide which apps get app refresh time and when. This is a complex issue, one that I’m not going to try to summarise here, but the take-home message is that, if you expect that the app refresh mechanism will grant you background execution time, say, every 15 minutes, you’ll be disappointed. In fact, there are common scenarios where it won’t grant you any background execution time at all! Watch the talk for the details.

When the user ‘force quits’ an app by swiping up in the multitasking UI, iOS interprets that to mean that the user doesn’t want the app running at all. So:

  • If the app is running, iOS terminates it.

  • iOS also sets a flag that prevents the app from being launched in the background. That flag gets cleared when the user next launches the app manually.

This gesture is a clear statement of user intent; there’s no documented way for your app to override the user’s choice.

Note In some circumstances iOS will not honour this flag. The exact cases where this happens are not documented and have changed over time.

Finally, if you have questions about background execution that aren’t covered by the resources listed here, please open a new thread on DevForums with the details. Tag it appropriately for the technology you’re using; if nothing specific springs to mind, use Background Tasks. Also, make sure to include details about the specific problem you’re trying to solve because, when it comes to background execution, the devil really is in the details.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + ""

Change history:

  • 2024-03-21 Added a discussion of ‘force quit’.

  • 2023-05-11 Added a paragraph that explains a common misconception about the app refresh mechanism. Made other minor editorial changes.

  • 2021-08-12 Added more entries to the common questions list, this time related to networking and IPC. Made minor editorial changes.

  • 2021-07-26 Extended the statement about what’s not possible to include “running code periodically at a guaranteed interval”.

  • 2021-07-22 First posted.

Up vote post of eskimo