Your suggestion aligns well with how Ruby on Rails tends to handle this. All of the stuff in your list of workloads would be considered “jobs” and they get enqueued asynchronously and run at some later time. The jobs run in another process, and can even be (often are) on another server so it’s not bogging down the main app, and they can communicate their success or failure via the main database.