Decommission a Service Without Breaking Its Dependents
Retire an internal service by proving who still calls it, serving explicit 410 responses, revoking access, and deleting data only after the retention window.
Objective
Retire a service safely by finding every dependent, migrating or redirecting traffic, and removing data only after the retention and approval requirements are met.
Environment
- Named service owner and written business approval for retirement
- Access logs from the gateway, service mesh or load balancer covering at least ninety days
- A code search across repositories for the service hostname and client library
- An archive location for configuration, data exports and runbooks
- A retention policy that defines when data and backups may be deleted
Steps
1. Confirm ownership and approval
Record the business owner, the replacement service if any, the retirement date and the data retention requirement in a signed decision record.
Expected state: A named approver has signed off and the retirement date is visible to all engineering teams.
2. Discover every consumer
Combine gateway logs, service mesh telemetry, DNS query logs and a repository search for the hostname to list every caller and scheduled job.
Expected state: Every consumer has an owner, a migration status and a target replacement.
3. Announce and serve a sunset signal
Add a Sunset header and return 410 Gone for retired paths while keeping read-only endpoints available during the migration period.
Expected state: Callers receive an explicit deprecation signal and the remaining request volume is attributable to named teams.
4. Remove traffic and credentials
Detach the service from DNS and the load balancer, revoke its API keys, webhook subscriptions and database roles, and disable its CI pipeline.
Expected state: No new connections reach the service and all credentials associated with it are revoked.
5. Archive and delete
Export the final data and configuration to the archive location, wait for the retention window, then delete the data stores, backups and infrastructure.
Expected state: The archive is readable and the production resources are deleted only after the retention date.
Decision points
Should traffic be redirected or returned as gone?
- Redirect to the replacement service
- Return 410 Gone with a migration link
Redirect only when request semantics match exactly; otherwise return 410 so callers fail visibly instead of silently writing to the wrong system.
How long should the old service stay read-only?
- Keep read-only endpoints during the migration window
- Turn everything off on the retirement date
Keep reads available until the last named consumer confirms migration, then stop all traffic on the announced date.
Who approves data deletion?
- The service owner alone
- The data owner and compliance reviewer
Require the data owner and compliance reviewer; deleting the last copy of regulated data is irreversible and cannot be undone by redeploying code.
Expected outcome
The service is removed from production with every dependent migrated, credentials revoked, and retained data archived under the approved policy.
Verification
Check that DNS returns no record, the load balancer has no listener, requests to the old hostname fail with 410 or connection refused, and the credential inventory shows no active keys.
Cleanup
Remove temporary redirects and monitoring, close the service catalog entry, and record the deletion date and archive location in the decision record.
Retirement starts with evidence, not a shutdown
The dangerous part of decommissioning is the caller nobody knew about: a nightly report, a partner integration or a cron job in an account that predates the service catalog. Gather ninety days of gateway and DNS logs, search every repository for the hostname, and ask each platform team directly. A caller list built only from dashboards will miss batch traffic that runs once a month.
Make the shutdown visible
Return a clear signal instead of a timeout. The gateway rule below keeps the old path answering with 410 Gone, adds a Sunset header and points callers at the replacement, which turns silent failures into actionable errors.
location /api/legacy-reports/ {
add_header Sunset "2026-12-01T00:00:00Z" always;
add_header Link "<https://api.example.com/v2/reports>; rel=\"successor-version\"" always;
return 410;
}
Safety checks
Revoke credentials only after the last consumer has migrated; revoking early creates an outage that looks like a bug in the replacement. Export the final database contents and configuration before deleting anything, and verify the archive restores. Remove the service from the catalog, DNS, monitoring and on-call rotation in the same change window so nothing pages for a service that no longer exists.
Rollback
Before data deletion, rollback means redeploying the service from infrastructure as code, restoring DNS and re-enabling the pipeline; keep the image and configuration available for thirty days to make that possible. After the retention window and the approved deletion, rollback is limited to restoring the archive into a new environment. Deleting the final data copy and its backups is the irreversible step; require data-owner and compliance sign-off before it happens.