I haven't ever found an answer to this when reading developer documentation.
When using main and private queue contexts in
In most cases the current best practice is to start with
NSPersistentContainer. Its methods point to good practices for dealing with managed object contexts.
NSPersistentContainer has a property
viewContext which uses a main queue concurrency. As its name implies, it's good for use directly with the UI, and on the main queue. Use this context for those cases. Don't create new main queue contexts.
It also has a couple of ways to do background work on private queues, via
performBackgroundTask. In most cases you can use either of these when you need to do background work, and not bother keeping a reference to a long-lived background context. One caveat is that since they use separate background queues, it's possible for one background context to be executing at the same time as another. If that seems possible in your case, you might want to hold onto a background context to avoid that possibility. Otherwise your background contexts might need to merge changes made on other background contexts, which can get ugly fast.
There are exceptions to all of the above, but this is a good starting point. If this doesn't fit with your app for some reason, come back with another question detailing why.