A budget that three workers can share
Enforce task limits through atomic reservations and repeat-safe settlement, including the uncomfortable case where a timed-out operation may still be spending.
Retire intake, accepted jobs and external authority in a deliberate order, so a late event cannot revive an obsolete process.
The old reminder worker is off, but a schedule, delayed webhook or queued retry may still know how to start it again. Retirement has to reach those entrances as well as the jobs already accepted. I would trace one late event through the proposed shutdown before deleting the application, so the replacement team knows whether it will receive that work or merely inherit another unexplained failure.
Retirement is a lifecycle change with accepted work on both sides of it. We need to stop new intake, account for work already accepted and remove the authority that would let obsolete machinery act again. Merely deleting the visible application can strand the work while leaving the triggers and credentials alive.
Take a fictional supplier-reminder automation replaced by a new procurement system. The old service has a weekday schedule, an incoming webhook endpoint, a queue and a shared email credential. At the retirement decision, it contains 24 accepted reminders: 18 ready, four waiting for a supplier response and two with uncertain send outcomes. The objective is not to make all those counters disappear. It is to give each commitment a deliberate outcome.
Name a cutoff and decide how the service drains. Work accepted before it can finish, transfer or be cancelled with an explanation. After it, new reminders need the replacement route or an explicit refusal. Those choices belong together: closing intake prevents new obligations, while the drain policy deals with obligations the old service already holds. Neither can be inferred from the main worker no longer running.
Inventory schedules, event subscriptions, manual buttons, API callers and recovery routes. A forgotten administrative script can keep creating jobs after the main schedule is disabled. A provider subscription can continue sending events even when the web application has been removed. Record who owns each entrance and how its retirement will be verified.
For the reminder service, disable or redirect the weekday schedule under a recorded change. Update the producer of new procurement events so the replacement route owns future work. Remove the obsolete provider subscription when the migration contract allows it. Do not rely on a dead endpoint to communicate retirement to a sender that will interpret failure as a reason to retry.
Stripe’s webhook documentation is a useful example of a producer with delivery retries and event-handling requirements. The wider lesson is to inspect the actual sender’s retry and registration contract. A service can receive traffic after the team’s intended cutoff because delivery and business acceptance are not the same event. Avoid borrowing one provider’s time window as a universal waiting period.
Decide what late deliveries should receive. A small endpoint may remain to recognise duplicates or record a terminal outcome. Returning success and discarding an event is appropriate only when the business has established that no work remains due and retains that decision. Otherwise the sender sees successful delivery while neither process takes responsibility. Keep the reason a late event needs no further action alongside the response, rather than let endpoint behaviour make that business decision silently.
For the 24 reminders, classify outcomes by the business action still needed. The 18 ready reminders might transfer to the new system with stable source identities. The four waiting for a response may need a monitored handover. The two uncertain sends require investigation before the replacement system sends anything again. These are proposed decisions for the example, not a rule that every queue should be drained the same way.
The receiving process needs to acknowledge each transfer. An exported CSV does not show that the new system imported it or that somebody accepted ownership. Link source and destination job identities so a repeat transfer is recognisable, and prevent the old sender acting on the same reminders. Then the eighteen ready items have actually changed hands, rather than simply acquired another copy in a second system.
A claimed reminder can remain active after intake stops. Before transferring its copied record, pause execution where needed and account for in-flight attempts, including sends whose results remain uncertain. The handover must establish which system may act on each reminder. Without that ownership boundary, a successfully imported queue can overlap with the old worker and produce duplicate supplier messages despite clean intake shutdown.
For reminders intentionally cancelled, preserve a reason and the relevant decision. Some work genuinely becomes unnecessary when the process changes. Cancellation is a valid terminal outcome if somebody owns that judgement. Silently deleting the row because the old database is about to be removed makes the same decision without leaving anyone able to explain it.
A proposed retirement plan for an invented supplier-reminder service.
Scroll sideways to see all columns.
| Accepted work | Count | Retirement treatment |
|---|---|---|
| Ready reminders | 18 | Acknowledged transfer; prevent old sender |
| Waiting for response | 4 | Named monitored handover |
| Send outcome unknown | 2 | Investigate before replacement send |
| Total commitments | 24 | Each needs an accountable outcome |
Once the accepted work has accountable outcomes, revoke the old service’s ability to perform new effects. Remove or rotate the dedicated credentials and provider registrations according to their actual dependencies. A shared credential complicates this step because another live process may still need it. That is a dependency to resolve, not a reason to leave obsolete access permanently available.
Check the provider side when withdrawing authority. Deleting an environment variable in one deployment leaves any copies in old workers or schedules untouched. If another live service shares the credential, identify and migrate its use before revoking it. Record when the obsolete route actually lost the ability to send. That gives the replacement team a firmer answer than a deployment diff showing one stored value was removed.
Do not revoke access required to investigate unresolved effects without planning an alternative. A read-only account or controlled support route may be needed to establish whether the two uncertain reminders were sent. Execution authority and investigation access can have different retirement schedules. Grant the latter narrowly rather than keeping a broad sending credential simply because it makes diagnosis convenient.
Retained operating history needs an owner and retrieval route after workers and execution credentials are gone. Preserve the records that explain a reminder's transfer, cancellation or uncertain send under the relevant retention policy. A backup alone may not make those facts practically accessible. The support route should be able to find the meaningful outcome without having to restart an obsolete service to interpret it.
The reminder retirement has two uncertain sends requiring evidence after execution is disabled.
Scroll sideways to see all columns.
| Access or artefact | Retirement treatment | Purpose |
|---|---|---|
| Sending credential | Revoke after dependency resolution | Prevent obsolete new effects |
| Narrow read-only investigation route | Retain only as required | Establish the two uncertain outcomes |
| Reminder history | Archive with owner and retrieval route | Explain transfer, cancellation and send evidence |
An observation window helps verify that no unexpected trigger remains, but its length should match known schedules and sender behaviour. Seven quiet days do not account for a monthly job. Combine observed traffic with the entrance inventory and provider configuration, rather than treating silence as proof that nothing can happen.
A retirement report for the example could account for all 24 reminders: 18 acknowledged transfers, four named handovers and two unresolved sends with an investigation owner. If the two remain unresolved, execution can be disabled while the retirement is still incomplete at the business level. Keep that limitation visible. A project status should not force uncertainty to vanish because somebody wants the old service off the billing account.
Exercise a late webhook, a delayed retry and an old manual button. Check that each follows the intended terminal or replacement route and cannot restart obsolete execution. Also check the archived status link a support colleague might still use. A blank error page can turn a well-managed retirement into an avoidable support mystery.
There is a legitimate trade-off in retaining a small compatibility endpoint for late events. It adds a little maintenance but can make the transition explainable. Keeping the entire old application alive indefinitely carries a different cost. Choose the smallest supported surface that fulfils the remaining contract, then give that surface its own removal condition.
Follow a late event and an old status link through the retired reminder service. The event should reach the agreed terminal or replacement route; the link should still let support explain a supplier message. A quiet worker is easy to observe. Those remaining routes tell the business whether it can actually let the old process go.
Working on a workflow like this? Hamsa helps finance and operations teams connect their tools and handle the exceptions, starting with one workflow.
See the Payment Operations PilotPrimary sources behind this article. Living documentation may change.

Practical engineering. A human perspective.
More about Hamsa Software and the person behind it. Editorial notes.