Application Retirement
Application retirement removes an application from active use through controlled decommissioning that preserves required data, transitions users to replacement systems, and terminates associated contracts and infrastructure. You execute this procedure after the retirement decision has been made through portfolio governance and a replacement solution (or explicit decision to discontinue the capability) has been identified.
Prerequisites
| Requirement | Detail |
|---|---|
| Retirement decision | Formal approval from application portfolio governance with documented rationale |
| Replacement identified | Successor application deployed and validated, or explicit decision to discontinue capability |
| Data owner assignment | Named individual accountable for data disposition decisions |
| Legal review | Confirmation of retention requirements and contractual obligations |
| User inventory | Complete list of active users, integrations, and dependent processes |
| Access | Administrative access to application, identity provider, and hosting infrastructure |
| Timeline | Minimum 90 days for standard applications; 180 days for applications with external users or complex integrations |
Before beginning retirement, confirm the replacement application is operational. Users cannot transition to a system that does not exist. For applications being discontinued without replacement, confirm stakeholders accept the capability loss and document this acceptance.
Verify data retention requirements by consulting records management schedules and any donor or regulatory requirements specific to the data held. An application holding grant-funded programme data requires verification against each donor’s retention terms before any data disposition occurs.
Gather these artefacts before proceeding:
Required documentation checklist:[ ] Application portfolio record (from portfolio management system)[ ] Vendor contract(s) with termination terms[ ] Data retention schedule applicable to application data[ ] User access list from identity provider[ ] Integration inventory (APIs, data feeds, SSO connections)[ ] Infrastructure inventory (servers, databases, storage)[ ] Backup and archive locations[ ] Compliance certifications held by applicationRoles
| Role | Responsibility | Typical assignee |
|---|---|---|
| Retirement lead | Coordinates all retirement activities and tracks completion | IT project manager or application owner |
| Data owner | Makes data disposition decisions and signs off on extraction/deletion | Business unit head |
| Technical lead | Executes technical decommissioning steps | Systems administrator or application specialist |
| Security lead | Validates access removal and security controls | IT security staff |
| Vendor manager | Handles contract termination and asset return | Procurement or IT operations |
For organisations without dedicated staff in each role, the IT lead combines technical lead, security lead, and vendor manager responsibilities. The data owner role cannot be combined with IT roles as it represents business accountability for data decisions.
Procedure
Phase 1: Planning and communication
- Create the retirement project record in your project tracking system with these milestones:
Milestone Target (days from start) ───────────────────────────────────────────────────────────── Stakeholder notification Day 0 Data extraction complete Day 30 User migration complete Day 60 Read-only period begins Day 75 Final decommissioning Day 90 Contract termination Day 90 Post-retirement review Day 120Adjust timelines based on user count and integration complexity. Applications with over 500 users or more than 10 integrations require 180-day timelines.
- Draft the stakeholder communication plan identifying all parties requiring notification:
Stakeholder category Notification method Lead time Owner ───────────────────────────────────────────────────────────────────── Active users Email + system banner 90 days Retirement lead Integration owners Direct meeting 90 days Technical lead External partners Formal letter 90 days Vendor manager Donor/funder Per agreement terms Per terms Data owner Executive sponsors Briefing 90 days Retirement lead IT support staff Team meeting 60 days Technical leadSend initial notification to all stakeholders. Include:
- Application name and retirement date
- Replacement application (if applicable) with access instructions
- Data migration timeline and user responsibilities
- Support contacts for questions
- Link to detailed transition guide
Place a system banner in the retiring application visible to all users:
┌─────────────────────────────────────────────────────────────────┐ │ NOTICE: This application will be retired on [DATE]. │ │ Please migrate to [REPLACEMENT] before this date. │ │ See [LINK] for migration instructions and support. │ └─────────────────────────────────────────────────────────────────┘Phase 2: Data extraction and migration
- Inventory all data within the application by category:
Data category Volume Retention req. Disposition ───────────────────────────────────────────────────────────────────── Active records 45,000 7 years Migrate Historical records 120,000 7 years Archive System logs 2.3 GB 1 year Archive subset User preferences 3,200 None Delete Temporary files 850 MB None Delete Attachments 15 GB 7 years Migrate- Execute data extraction based on the disposition decision for each category. For data requiring migration to the replacement system:
# Export data in portable format application-cli export --format json --output /exports/app-data-$(date +%Y%m%d).json
# Verify export integrity application-cli verify-export /exports/app-data-$(date +%Y%m%d).json # Expected output: "Export verified: 45000 records, checksum: abc123..."
# Generate field mapping for import migration-tool generate-mapping \ --source /exports/app-data-$(date +%Y%m%d).json \ --target replacement-app \ --output /mappings/field-map.yaml- For data requiring archival rather than migration, export to a long-term archive format:
# Create archival package with metadata archive-tool create \ --source /exports/historical-data.json \ --metadata "Application: OldApp, Retirement Date: 2024-11-15" \ --retention-years 7 \ --output /archives/oldapp-historical-$(date +%Y%m%d).tar.gz
# Generate archive manifest archive-tool manifest /archives/oldapp-historical-$(date +%Y%m%d).tar.gz
# Transfer to archive storage aws s3 cp /archives/oldapp-historical-$(date +%Y%m%d).tar.gz \ s3://org-archives/applications/oldapp/ \ --storage-class GLACIER- Validate migrated data in the replacement system. Compare record counts and perform spot checks on 50 randomly selected records:
# Compare record counts source_count=$(jq '.records | length' /exports/app-data-*.json) target_count=$(replacement-cli count-records --type imported)
if [ "$source_count" -eq "$target_count" ]; then echo "Record count matches: $source_count" else echo "MISMATCH: Source=$source_count, Target=$target_count" exit 1 fi
# Generate spot-check sample jq -r '.records | .[range(50)] | .id' /exports/app-data-*.json > /tmp/spot-check-ids.txt- Obtain data owner sign-off on extraction completion. Document this approval in the retirement project record:
Data Extraction Sign-off ───────────────────────────────────────────────────────────────── Application: [Name] Extraction date: [Date] Records migrated: [Count] Records archived: [Count] Records deleted: [Count]
I confirm the data extraction is complete and accurate.
Data Owner: ____________________ Date: ____________Phase 3: User transition
- Generate the user transition tracking list from your identity provider:
# Extract users with application access idp-cli list-users --application "OldApp" --format csv > /transitions/user-list.csv
# Sample output: # user_id,email,last_login,department,manager # u001,alice@example.org,2024-10-15,Programmes,bob@example.org # u002,carol@example.org,2024-09-28,Finance,david@example.org- Provision user access to the replacement application. For organisations using automated provisioning:
# Bulk provision from transition list idp-cli provision-users \ --application "NewApp" \ --source /transitions/user-list.csv \ --role "standard-user"
# Send credentials/instructions notification-cli send \ --template "replacement-app-access" \ --recipients /transitions/user-list.csvFor manual provisioning, work through the user list systematically, provisioning in batches of 25 users per day to manage support load.
- Track user migration progress weekly. Users who have not logged into the replacement application within 30 days of notification require direct follow-up:
# Identify users not yet migrated idp-cli compare-logins \ --old-app "OldApp" \ --new-app "NewApp" \ --since "2024-08-15" \ --output /transitions/not-migrated.csv
# Send reminder to non-migrated users notification-cli send \ --template "migration-reminder" \ --recipients /transitions/not-migrated.csv- Provide hands-on support sessions for users requiring assistance. Schedule 1-hour sessions with capacity for 10 users each:
Migration support schedule:
Session 1: Day 30 - 10:00-11:00 - General users Session 2: Day 30 - 14:00-15:00 - General users Session 3: Day 45 - 10:00-11:00 - Power users/trainers Session 4: Day 60 - 10:00-11:00 - Final catch-up- At day 60, contact managers of users who have not migrated. Escalate to department heads at day 75 if users remain on the old system without documented exceptions.
Phase 4: Integration decommissioning
- Inventory all integrations connected to the retiring application:
Integration inventory:
Integration ID Type Direction Target system Status ───────────────────────────────────────────────────────────────────── INT-001 API Inbound Finance system Active INT-002 API Outbound Reporting tool Active INT-003 File sync Bidirect Partner portal Active INT-004 SSO Inbound Identity provider Active INT-005 Webhook Outbound Notification svc Inactive- Contact each integration owner to coordinate disconnection. Provide 30 days notice for active integrations:
Integration disconnection notice:
To: [Integration owner] Subject: Disconnection of [OldApp] integration - Action required by [Date]
The integration between [OldApp] and [Target system] (INT-XXX) will be disconnected on [Date] as part of application retirement.
Required actions: 1. Confirm replacement integration to [NewApp] is operational 2. Schedule disconnection window 3. Confirm post-disconnection testing plan
Please respond by [Date - 14 days] to confirm readiness.- Disable integrations in sequence, starting with lowest-risk integrations to validate the process:
# Disable outbound webhooks first (lowest risk) integration-cli disable INT-005 --reason "Application retirement"
# Disable file synchronisation integration-cli disable INT-003 --reason "Application retirement"
# Disable API integrations integration-cli disable INT-001 --reason "Application retirement" integration-cli disable INT-002 --reason "Application retirement"
# SSO disabled last during final decommissioning- Verify each disconnection with the integration owner before proceeding to the next. Document confirmation in the retirement record.
Phase 5: Read-only period
- At day 75, switch the application to read-only mode. This allows users to reference historical data while preventing new data entry:
# Enable read-only mode application-cli set-mode --readonly --reason "Pre-retirement"
# Update system banner application-cli set-banner \ --message "This application is now READ-ONLY. No new data can be entered. Please use [NewApp] for all new work. This application will be permanently disabled on [Date]."- Disable all write operations at the application and database level:
-- Revoke write permissions from application service account REVOKE INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA app FROM app_service_account;
-- Verify read-only status SELECT grantee, privilege_type FROM information_schema.role_table_grants WHERE grantee = 'app_service_account';- Monitor for failed write attempts during the read-only period. Users encountering errors require additional migration support:
# Check application logs for write attempt errors grep -i "write denied\|readonly\|permission denied" /var/log/app/application.log
# Extract user IDs from failed attempts grep "write denied" /var/log/app/application.log | \ awk '{print $5}' | sort | uniq > /transitions/write-attempt-users.csv- Contact users who attempted writes during read-only period within 24 hours to provide migration assistance.
Phase 6: Final decommissioning
- At the retirement date, disable user authentication to the application:
# Remove application from identity provider idp-cli remove-application "OldApp"
# Verify removal idp-cli list-applications | grep -i "OldApp" # Expected: no output (application not found)- Disable SSO integration:
# Remove SAML/OIDC configuration idp-cli delete-saml-config --application "OldApp"
# Revoke OAuth clients idp-cli revoke-oauth-client --client-id "oldapp-client-id"- Stop application services:
# Stop application containers/services systemctl stop oldapp.service
# Disable automatic restart systemctl disable oldapp.service
# Verify service stopped systemctl status oldapp.service # Expected: "inactive (dead)"- Create final database backup before any deletion:
# Full database backup pg_dump -h localhost -U admin -d oldapp_production \ -F c -f /backups/oldapp-final-$(date +%Y%m%d).dump
# Verify backup integrity pg_restore --list /backups/oldapp-final-$(date +%Y%m%d).dump | head -20
# Copy to archive storage aws s3 cp /backups/oldapp-final-$(date +%Y%m%d).dump \ s3://org-archives/applications/oldapp/final-backup/ \ --storage-class GLACIER- Remove DNS entries pointing to the application:
# Remove A/CNAME records dns-cli delete-record --zone example.org --name oldapp --type A dns-cli delete-record --zone example.org --name oldapp --type CNAME
# Verify removal (allow DNS propagation time) dig oldapp.example.org # Expected: NXDOMAIN or no answer- Revoke TLS certificates:
# Revoke certificate certbot revoke --cert-name oldapp.example.org
# Delete certificate files certbot delete --cert-name oldapp.example.orgDecommission infrastructure based on hosting model:
For cloud-hosted applications:
# Terminate compute instances aws ec2 terminate-instances --instance-ids i-0123456789abcdef0
# Delete load balancer aws elbv2 delete-load-balancer --load-balancer-arn arn:aws:elasticloadbalancing:...
# Remove security groups (after instances terminated) aws ec2 delete-security-group --group-id sg-0123456789abcdef0For on-premises applications:
# Power down virtual machines virsh shutdown oldapp-vm
# Remove from hypervisor inventory virsh undefine oldapp-vm --remove-all-storage- Delete application data only after confirming archive copies exist and retention requirements allow deletion:
# Verify archives exist aws s3 ls s3://org-archives/applications/oldapp/ # Confirm final-backup and historical archives present
# Drop database (irreversible) psql -h localhost -U admin -c "DROP DATABASE oldapp_production;"
# Remove application files rm -rf /opt/oldappPhase 7: Vendor and contract termination
- Review vendor contract termination terms. Extract key dates and requirements:
Contract termination checklist:
Contract ID: VENDOR-2021-045 Vendor: ExampleSoft Inc. Notice period: 90 days Notice deadline: [Date - 90 days before renewal] Termination fee: None (if notice given) Data return clause: Yes - 30 days post-termination Asset return: License keys, documentation- Send formal termination notice within the required notice period:
TERMINATION NOTICE
To: ExampleSoft Inc. Contracts Department From: [Organisation Name] Date: [Date] Re: Contract VENDOR-2021-045 - Notice of Termination
We hereby provide notice of termination for Contract VENDOR-2021-045 effective [Termination Date], in accordance with Section [X] of the agreement.
Please confirm: 1. Receipt of this notice 2. Final invoice date 3. Data return/deletion schedule 4. Asset return instructions
Contact: [Vendor Manager Name, Email, Phone]- Request data return or deletion certificate from vendor:
DATA DISPOSITION REQUEST
Pursuant to our contract termination, please provide:
[ ] Complete export of all organisation data in [format] [ ] Written certification of data deletion from vendor systems [ ] Confirmation that no copies retained except as legally required
Required by: [Date + 30 days]- Return vendor assets (hardware tokens, documentation, license certificates):
Asset return manifest:
Item Serial/ID Return method ───────────────────────────────────────────────────────────── Hardware token HW-12345 Courier License certificate LIC-2021-045 Email (scanned) API documentation N/A Confirm deleted- Confirm final invoice and close purchase order:
# Close purchase order in finance system finance-cli close-po --po-number PO-2021-0456 --reason "Contract terminated"
# Update vendor record vendor-cli update --vendor-id V-123 --status "Inactive" \ --note "Contract terminated [Date], application retired"- Obtain and file vendor’s data deletion certificate. This document is required for compliance records.
Phase 8: Documentation and knowledge transfer
- Update the application portfolio record to reflect retired status:
# Application portfolio record update application: id: APP-045 name: OldApp status: Retired retirement_date: 2024-11-15 replacement: NewApp (APP-078) data_disposition: migrated_to: NewApp archived_location: s3://org-archives/applications/oldapp/ retention_until: 2031-11-15 documentation: retirement_record: /docs/retirements/APP-045-retirement.pdf archive_manifest: /docs/retirements/APP-045-archive-manifest.csv- Create the retirement summary document:
APPLICATION RETIREMENT SUMMARY
Application: OldApp (APP-045) Retirement Date: 2024-11-15 Retirement Lead: [Name]
TIMELINE ───────────────────────────────────────────────────────────── Notification sent: 2024-08-15 Data extraction complete: 2024-09-15 User migration complete: 2024-10-15 Read-only period: 2024-10-30 - 2024-11-15 Final decommissioning: 2024-11-15 Contract terminated: 2024-11-15
DATA DISPOSITION ───────────────────────────────────────────────────────────── Records migrated: 45,000 (to NewApp) Records archived: 120,000 (to S3 Glacier) Records deleted: 4,050 (temporary/preference data) Archive retention: Until 2031-11-15
USER TRANSITION ───────────────────────────────────────────────────────────── Users transitioned: 312 Users deactivated: 8 (left organisation) Exceptions granted: 0
INTEGRATIONS DECOMMISSIONED ───────────────────────────────────────────────────────────── INT-001: Finance system API INT-002: Reporting tool API INT-003: Partner portal sync INT-004: SSO
INFRASTRUCTURE DECOMMISSIONED ───────────────────────────────────────────────────────────── Servers: 2 (i-0123..., i-0456...) Databases: 1 (oldapp_production) Storage: 50 GB recovered
VENDOR ───────────────────────────────────────────────────────────── Vendor: ExampleSoft Inc. Contract terminated: 2024-11-15 Data deletion cert: Received 2024-11-28 Final invoice: Paid 2024-11-30
APPROVALS ───────────────────────────────────────────────────────────── Data owner sign-off: [Name], 2024-09-15 Security sign-off: [Name], 2024-11-15 IT Director sign-off: [Name], 2024-11-15- Archive application documentation (user guides, technical documentation, configuration records) to the documentation archive:
# Package documentation tar -czf /archives/oldapp-documentation.tar.gz /docs/applications/oldapp/
# Upload to archive storage aws s3 cp /archives/oldapp-documentation.tar.gz \ s3://org-archives/applications/oldapp/documentation/- Update knowledge base to redirect users seeking information about the retired application:
# OldApp (Retired)
Status: Retired as of 2024-11-15
Replacement: [NewApp](/docs/applications/newapp/)
Historical data: Contact IT Service Desk for archived data requests. Reference retirement record APP-045.
Documentation archive: Available upon request for compliance purposes.- Brief IT support staff on handling queries about the retired application. Provide standard responses:
Support response templates:
Q: "I need access to OldApp" A: "OldApp was retired on [Date]. Please use NewApp for this function. Access instructions: [link]. If you need historical data from OldApp, please submit a data request ticket."
Q: "I need data from OldApp" A: "OldApp data is archived. Please submit a ticket with: - Specific data needed - Business justification - Timeframe of data Data requests are processed within 5 business days."Verification
After completing all phases, verify the retirement is complete:
# Verify application unreachablecurl -I https://oldapp.example.org# Expected: Connection refused or DNS resolution failure
# Verify no active users in identity provideridp-cli list-users --application "OldApp"# Expected: "Application not found" or empty list
# Verify no active integrationsintegration-cli list --application "OldApp"# Expected: Empty list or all marked "Disabled"
# Verify infrastructure decommissionedaws ec2 describe-instances --filters "Name=tag:Application,Values=OldApp"# Expected: Empty or all instances in "terminated" state
# Verify database droppedpsql -h localhost -U admin -c "\l" | grep oldapp# Expected: No output
# Verify vendor contract closedvendor-cli show --vendor-id V-123 --contract VENDOR-2021-045# Expected: Status "Terminated"Complete this verification checklist:
Post-retirement verification:
[ ] Application URL returns error (not accessible)[ ] No users have application access in identity provider[ ] All integrations disabled or removed[ ] All infrastructure terminated or deallocated[ ] Database dropped (after backup confirmed)[ ] DNS records removed[ ] TLS certificates revoked[ ] Vendor contract terminated[ ] Data deletion certificate received[ ] Final invoice paid[ ] Portfolio record updated to "Retired"[ ] Retirement summary document filed[ ] Support staff briefed[ ] Knowledge base updatedRollback
Rollback is possible only before Phase 6 (final decommissioning). After database deletion and infrastructure termination, rollback requires full application redeployment from backups.
To rollback during Phases 1-5:
- Remove read-only restrictions:
GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA app TO app_service_account;- Re-enable integrations in reverse order of disconnection:
integration-cli enable INT-001 --reason "Retirement rollback"- Update system banner to indicate retirement cancelled:
application-cli set-banner --message "Application retirement has been cancelled. Normal operations resumed."- Notify all stakeholders of rollback with revised timeline or cancellation.
After Phase 6, recovery requires:
- Restore database from final backup
- Redeploy application from last known configuration
- Recreate DNS entries
- Issue new TLS certificates
- Re-establish integrations
- Re-provision user access
This process takes 2-5 days depending on application complexity. Document the recovery in an incident record.
Troubleshooting
| Symptom | Cause | Resolution |
|---|---|---|
| Users report cannot access replacement application | Provisioning not complete or incorrect permissions | Verify user exists in replacement app; check role assignment; re-run provisioning for affected users |
| Integration errors after disconnection | Dependent system not updated to use replacement | Contact integration owner; verify replacement integration configured; temporarily re-enable old integration if critical |
| Data migration count mismatch | Export incomplete or import errors | Re-run export with verbose logging; check for encoding issues; compare checksums; manually reconcile differences |
| Vendor refuses data deletion certificate | Contract ambiguity or vendor retention requirements | Escalate to legal; review contract terms; document vendor position; assess risk of retained data |
| Users discover missing data after retirement | Data not included in migration scope or archive | Check archive manifest; restore from final backup if within retention; document for future retirements |
| Archived data unreadable | Format incompatibility or encryption key issues | Verify archive format; check encryption keys in secrets manager; test restore procedure |
| Contract termination fee unexpected | Notice period missed or misunderstood terms | Review contract; negotiate with vendor; escalate to procurement; document for future reference |
| Integration owner unresponsive | Staff turnover or unclear ownership | Escalate to department head; check integration documentation for alternative contacts; proceed with documented notification attempts |
| Read-only mode not enforced | Application-level restriction insufficient | Implement database-level restrictions; review application configuration; add network-level blocks if needed |
| DNS still resolving after deletion | DNS cache or propagation delay | Wait 24-48 hours; check authoritative nameservers directly; clear local DNS cache |
| Compliance audit requests data from retired application | Retention requirements not fully understood | Retrieve from archive storage; document retrieval process; review retention schedule accuracy |
| Former users request historical reports | Business need for retired application data | Extract from archive; provide one-time export; consider building archive query capability for frequently requested data |
Retirement workflow
+------------------------------------------------------------------+| APPLICATION RETIREMENT FLOW |+------------------------------------------------------------------+
+------------------+ | Retirement | | Decision | | (Portfolio Mgmt) | +--------+---------+ | v +--------+---------+ +------------------+ | Prerequisites |---->| Missing items? | | Verified? | | Resolve before | | | | proceeding | +--------+---------+ +------------------+ | | Yes v +--------+---------+ | Phase 1: | Day 0 | Planning & |----> Stakeholder notification | Communication | Communication plan +--------+---------+ | v +--------+---------+ | Phase 2: | Day 1-30 | Data Extraction |----> Export data | & Migration | Migrate to replacement | | Archive historical +--------+---------+ | v +--------+---------+ | Phase 3: | Day 1-60 | User |----> Provision replacement access | Transition | Track migration progress | | Support sessions +--------+---------+ | v +--------+---------+ | Phase 4: | Day 60-75 | Integration |----> Notify integration owners | Decommissioning | Disable integrations +--------+---------+ | v +--------+---------+ | Phase 5: | Day 75-90 | Read-Only |----> Enable read-only mode | Period | Monitor for write attempts +--------+---------+ Final user migration | v +--------+---------+ | Phase 6: | Day 90 | Final |----> Disable authentication | Decommissioning | Stop services | | Create final backup +--------+---------+ Delete data | v +--------+---------+ | Phase 7: | Day 90 | Vendor & |----> Send termination notice | Contract | Request data deletion cert +--------+---------+ Return assets | v +--------+---------+ | Phase 8: | Day 90-120 | Documentation |----> Update portfolio record | & Knowledge | Archive documentation | Transfer | Brief support staff +--------+---------+ | v +--------+---------+ | Verification & | Day 120 | Post-Retirement |----> Complete checklist | Review | File retirement summary +------------------+Data handling decision tree
+-------------------+ | Data category | | identified | +---------+---------+ | +-------------------+-------------------+ | | | v v v +--------+------+ +------+-------+ +-----+--------+ | Active | | Historical | | Temporary/ | | operational | | records | | system data | | data | | | | | +--------+------+ +------+-------+ +-----+--------+ | | | v v v +--------+------+ +------+-------+ +-----+--------+ | Retention | | Retention | | Retention | | required? | | required? | | required? | +--------+------+ +------+-------+ +-----+--------+ | | | +----+----+ +----+----+ +----+----+ | | | | | | v v v v v v Yes No Yes No Yes No | | | | | | v v v v v v +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ |Migrate| |Migrate| |Archive| |Delete | |Archive| |Delete | |to new | |if | |to | |after | |subset | |immed- | |system | |needed | |cold | |confir-| |per | |iately | | | |by | |storage| |mation | |policy | | | | | |users | | | | | | | | | +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ | | | | | | +----+----+---------+---------+---------+---------+ | v +--------+--------+ | Document | | disposition in | | retirement | | record | +-----------------+