
ASP.NET Core background work needs a recovery design whenever a user expects an operation to survive a process restart. Running code outside the request handler answers where work executes. It does not answer where unfinished work is recorded or how another process knows what to resume.
Microsoft's hosted-service documentation describes application lifetime methods and notes that unexpected process failure can prevent the shutdown method from running. A recovery plan therefore cannot depend entirely on graceful shutdown code.
Define the operation the user recognizes
Use a concrete task such as preparing an export or transferring a file. Give it a stable identity and distinguish accepting the request from completing the work. The interface should be able to show that an operation exists even when no worker currently holds it.
Decide what must survive: the input reference, owner, requested action, attempt history and final result may all matter. Store only what the task needs, with appropriate retention and access controls.
The ASP.NET Core product catalogue can help identify workflows worth studying. InTray describes file-oriented desktop work, but its association does not establish whether it uses hosted services or a particular queue. The design here is independent guidance.
Find the dangerous interruption points
Write a timeline from accepted request to durable completion. Mark every step that touches another system. If the process stops immediately after a destination accepts a file, the local record may still say “sending.”
That uncertain state deserves a defined reconciliation path. Retrying from the beginning can be safe for some operations and harmful for others. An export written under a stable result key differs from an external action that creates a new object on every call.
Do not call every unsuccessful attempt a fresh job. Preserve the relationship between the original user request and its later attempts.
Make repeated execution understandable
Where possible, use operation keys or uniqueness rules so repeated processing produces one intended result. Check the capabilities of the actual destination; an internal identifier alone cannot make an external service idempotent.
Record enough progress to decide whether to resume, reconcile or ask for assistance. Avoid storing progress so frequently that it becomes the dominant workload. The correct checkpoints follow meaningful side effects, not arbitrary percentages.
A “cancel” button also needs a contract. Specify whether it stops future work, interrupts current computation or merely prevents delivery of the result. Show the outcome that actually occurred.
Keep ownership attached to the job
A worker should not treat an internal queue entry as unconditional permission. Confirm that the job belongs to the expected account and that its action remains permitted at the relevant execution boundary.
For account deletion or revoked access, define the intended behavior before implementing cleanup. Retaining an audit reference can be necessary without retaining the original private payload indefinitely.
These decisions are separate from choosing an in-process service, queue library or managed worker platform.
Rehearse recovery in an isolated environment
Create a synthetic operation and stop the worker at selected points. Restart it, inspect the visible status and confirm the final result count. Include an unavailable dependency and an uncertain response, not only a clean exception before work begins.
Save evidence of what resumed and what required reconciliation. A passing happy-path request does not demonstrate durable recovery.
The client and service boundary guide helps identify which system owns each result. Once those boundaries are explicit, the background-work design becomes a set of testable promises rather than an assumption about process lifetime.


