A database migration can appear finished while its temporary structures remain in daily use. An old view still supports a monthly report. A synchronisation trigger keeps an earlier column current. An export uses a compatibility name that nobody remembers owning. Removing these structures too soon causes failures; retaining them indefinitely makes the next change harder to understand.
Retirement is therefore a separate engineering task with its own evidence and acceptance criteria. A new application working correctly proves that the new path works. It does not prove that every old reader and writer has stopped using the previous path.
The objective is to establish what remains dependent on the old contract, move or deliberately retain those dependencies, and remove only what has been shown to be unnecessary. That process needs more than a calendar date and a reassuring lack of recent support calls.
Identify the contract being retired
A compatibility structure can be a view, column, table, stored procedure, alias or synchronisation mechanism. Its purpose is to let an older consumer continue working while the underlying representation changes. The consumer may be a deployed application, report, integration or manually operated script.
Record what the structure promises. An old customer view might preserve column names, data types, row filters and access permissions. A legacy status column might preserve a particular interpretation of combined business states. Consumers can depend on any of these properties, not just the object’s name.
Define the intended replacement and its limits. A new view that returns the same rows with a different column order may still break a file export that relies on positional fields. A replacement that has stronger permissions may be correct but still require consumers to adopt a new service identity.
Keep the retirement unit small enough to understand. Removing a view, a trigger and two columns together may be reasonable if they form one compatibility mechanism. Combining unrelated removals because their dates coincide makes it harder to attribute a failure and harder to restore only the necessary part.
Build a consumer register from several kinds of evidence
Start with declared dependencies: application owners, scheduled jobs, report catalogues and integration inventories. Add references found in source code and configuration. Then compare those with observed use where the database and operating environment provide suitable telemetry.
Each source has blind spots. Source-code search can miss dynamically constructed SQL and externally maintained scripts. Runtime logs may omit statements, retain too little history or identify only a shared service account. An inventory may list a report that has been replaced, while missing a spreadsheet that is still refreshed manually.
For each consumer, record its owner, purpose, access path, frequency and migration state. Distinguish an active consumer from an abandoned reference that cannot execute. Both may deserve cleanup, but only the active one currently depends on the compatibility contract.
An unowned dependency is unresolved work. Do not convert it into “unused” simply because nobody immediately recognises it. Trace its scheduling, credentials or output destination until someone can explain whether it still serves a business purpose. Avoid exposing passwords or copying sensitive query parameters while doing this investigation.
Treat dependency catalogues as useful but incomplete
Database catalogues can identify relationships between stored objects, such as a view that depends on a table. They help establish an order for reviewing and removing related structures. They also provide a way to detect that a proposed removal has a wider scope than expected.
They cannot generally identify every consumer outside the database. A spreadsheet, application string or command assembled at runtime may have no stored dependency entry. Lack of a catalogue dependency is therefore not proof that nobody uses an object.
Even stored code can have implementation-specific limits. PostgreSQL’s dependency-tracking documentation explains that dependency recognition differs for some function-body forms. Review the actual engine and object type rather than assuming every reference is recorded in the same way.
Treat a cascading removal as an action whose complete effect must be reviewed, not a convenient way to silence a dependency error. A dependency error can be valuable evidence of an object that still needs attention. The retirement plan should identify each intended removal explicitly.
Choose an observation period from business activity
A week without observed use may be persuasive for a frequently executed operational query. It says little about a report used at month end, a quarterly reconciliation or a recovery script used only during incidents. The required evidence depends on the consumer’s actual operating cycle.
Include quiet periods, seasonal work and exception paths in the review. An annual report may be important despite being absent from recent telemetry. A disaster-recovery procedure may never appear in ordinary production logs, yet still contain the old schema name.
Observation length alone cannot resolve every infrequent dependency. An owner can migrate a report and exercise it using a representative historical period rather than waiting for the next natural run. Document that rehearsal and its limitations. It provides different evidence from a real scheduled production execution.
Do not adopt historical textbook transition periods as universal modern defaults. A small application under one team’s control and a database shared by several independent organisations have different coordination needs. Establish the period from release schedules, consumer evidence and the consequences of a missed dependency.
Work through a retirement decision
This is an illustrative example. A workshop replaces a combined customer-status view with a clearer representation. Five consumers were initially identified: an order application, a dispatch report, a nightly export, a monthly reconciliation and a recovery checklist containing a diagnostic query.
After three weeks, the first three consumers use the replacement. Query telemetry shows no recent calls to the old view. That looks encouraging, but the monthly reconciliation has not yet run and the recovery query has not been rehearsed.
| Consumer | Evidence available | Remaining retirement work |
|---|---|---|
| Order application | Updated release and exercised workflow | Record accepted version |
| Dispatch report | Updated query and checked output | Record comparison result |
| Nightly export | Successful scheduled runs | Confirm downstream acceptance |
| Monthly reconciliation | Old definition still in catalogue | Update and rehearse |
| Recovery diagnostic | Old name in procedure | Update and test procedure |
Three of five consumers have completed migration evidence; two remain unresolved. Zero recent calls does not turn that into five completed migrations. The correct next action is to resolve the two remaining paths, not to extend the same incomplete observation and hope it becomes conclusive.
Suppose the reconciliation is updated and reproduces the expected rows for a completed month, while the diagnostic is tested against the replacement in a recovery rehearsal. Retirement can then proceed once the other acceptance conditions are satisfied. The decision is based on specific consumer evidence rather than a percentage alone.
Separate the end of writing from the end of reading
An old field may no longer accept authoritative writes but still support readers. A compatibility view may be read-only while a synchronisation trigger continues copying values for it. These are different dependencies and may be retired at different times.
Identify which representation is authoritative at each stage. If old and new paths can both accept changes, removing one synchronisation direction without changing write permissions can create divergence. A successful read test will not reveal that a rarely used old writer can still produce inconsistent data.
When old writes are retired, make the supported behaviour explicit. The system might reject those writes with a clear error while preserving reads during the remaining transition. It should not silently accept changes that no longer reach the authoritative representation.
The earlier discussion of changing a live database safely provides the broader change process. Retirement narrows the question: which compatibility promises remain necessary now, and what evidence permits each one to end?
Rehearse with the old structures actually absent
Tests performed while the old view still exists can miss accidental dependencies. An application may use the new contract in its normal path and fall back to the old name during an error. A report might still reference an old column even though its main query was updated.
Create a representative non-production environment in which the planned retirement has occurred. Exercise the migrated consumers, background jobs and operational procedures against that final state. The purpose is to discover dependencies that coexistence concealed.
Include clean installation and recovery paths. A fresh environment should reach the supported final schema through the documented migration process. A restored backup may begin at an earlier schema version and require changes before current applications can use it. Removing an old object from production does not remove this historical upgrade responsibility.
Use controlled test data that covers the business meanings preserved by the old structure. If the compatibility view used to combine several status conditions, exercise those conditions in the replacement. Merely proving that a query executes does not establish that it returns the intended population.
Specify recovery in terms of recoverable meaning
Recreating a dropped view from a saved definition can be straightforward if its underlying data and dependencies remain compatible. Recreating a dropped column is different if its values were removed and cannot be derived from the new representation without loss.
Write down what can actually be restored, from which artefact and within what operational constraints. A statement that recreates a column definition does not restore its previous contents. Likewise, restoring a table from an old backup may omit legitimate transactions accepted after that backup.
Consider whether restoring the old interface would still be safe for writes. A rollback that re-enables an obsolete writer can be worse than a temporary read failure if its assumptions no longer match current data. Recovery may need to restore a read-only compatibility path while keeping writes on the new representation.
Distinguish recovery of service from reversal of the migration. The fastest acceptable response to a missed report dependency may be to update that report, not restore the entire old schema. Define who makes that decision and what information they will need during the incident.
Review the final removal as a specific change
The removal plan should identify exact objects, dependencies, consumer evidence, checks and recovery actions. Someone unfamiliar with the migration’s daily history should be able to understand what will disappear and why each affected consumer is ready.
Check the order of operations. Removing a compatibility view before an associated permission or monitoring definition may have different consequences from removing an underlying table first. Engine behaviour varies, so rehearse the chosen sequence on the actual database technology and representative configuration.
Coordinate with deployment activity. An older application instance, delayed job or rollback release could begin using the old contract after the retirement checks were completed. The supported application-version range must be clear at the point of removal, including what happens if an application release is rolled back.
Avoid bundling an unrelated performance change into the same retirement. If query performance deteriorates after removal, the team should be able to distinguish the absence of compatibility structures from a simultaneous index or application change. A narrow change makes both validation and recovery more understandable.
Monitor for missing consumers and changed meaning
After removal, watch for more than database errors. A failed scheduled export may leave an old file in place, giving downstream users plausible but stale data. A report may catch an exception and display an empty table. These outcomes can hide a missed dependency behind apparently normal screens.
Use expected activity as a check: did the scheduled report complete, did its output arrive, and did its row population remain consistent with the agreed comparison? The exact checks should come from the consumer register rather than a generic dashboard of database health.
Retain enough evidence to distinguish a retirement regression from an unrelated failure. Record the released application versions, schema change identifier and relevant job outcomes. Logging should identify the operation without unnecessarily reproducing confidential business records.
Keep an observation period after removal that covers the consumers’ relevant cycles. Completion is not the moment the removal statement succeeds. It is the point at which the agreed final state has survived the checks needed to establish that the business process still works.
Define a specific response for a newly discovered consumer. Record what it does, whether it reads or writes, and which business deadline is affected. That information helps distinguish a temporary compatibility restoration from a permanent reason to retain the old structure. An exception should become visible work with an owner and a revised decision, rather than an undocumented restoration that makes the retirement record inaccurate.
Close the temporary mechanism completely
Once retirement is accepted, update operational documentation, deployment scripts, examples and monitoring definitions. Otherwise an old recovery note or copied query can reintroduce the retired name during a later incident.
Keep the migration history and the evidence explaining the decision. Closing temporary infrastructure should reduce active complexity without erasing the record needed to understand older backups or historical releases. Mark obsolete procedures clearly so they are not confused with current instructions.
If a consumer must retain the old contract, make that an explicit supported interface with an owner and a maintenance obligation. Calling it temporary indefinitely hides its real cost. A consciously maintained compatibility service is easier to govern than an abandoned mechanism that happens to keep working.
For a small business, a short consumer register and a realistic rehearsal often provide more value than an elaborate change calendar. The essential discipline is to replace assumptions about non-use with evidence. A migration is easier to maintain when the final supported structure is clear and the old one has a deliberate, tested end.
Source basis: original KEVOS analysis of Removing Deprecated Schema, Choose a Sufficient Transition Period and related testing sections in the supplied Refactoring Databases: Evolutionary Database Design. Dependency limitations were checked against the linked PostgreSQL documentation. The consumer register is illustrative.