Returning to an earlier program does not necessarily restore a working service. Data may already use a structure that the older code cannot read or safely write.
I compared declared code read/write schemas with synthetic data versions without changing an actual deployment. The purpose is to examine rollback as a relationship between code and data rather than a file replacement.
Code and data do not necessarily return together
The old release in this example reads and writes only schema one. With schema-two data, choosing that release produces readable false, writable false and a blocked result. Nothing is executed. Possessing an older program does not establish that the earlier working business state can be reconstructed.
The function does not analyze an executable. Developers must verify that declared schema support matches actual code behavior through separate tests. This implementation calculates agreement once those declarations are supplied. It is neither a tool that repairs false compatibility claims nor an automatic recovery system.
Readable does not mean writable
A bridge release can declare that it reads schemas one and two but writes only schema two. Against schema-one data it becomes read_only. Merely reading does not automatically convert and overwrite records. Distinguishing inspection from mutation gives a more actionable result than a single compatible checkbox.
A read-only value does not disable a real button or enforce an API rule. The service must apply the same policy at its write endpoint and job executor. Hiding a save control in the browser is insufficient. This module has no such endpoints, so policy calculation and enforcement remain explicitly separate responsibilities.
A conversion proposal changes the return path
Migration preview preserves the original schema-one input and proposes schema two. A regression check passes that proposal to the old release contract and observes rejection. Even before application, the preview exposes how a return path would change. That makes compatibility a question to answer before changing data.
After real application, a plan must account for the preserved source and subsequent new work. Blindly restoring an old backup can discard operations completed later. The example has no reverse conversion or actual restore action. It explains the relationship requiring review without claiming a recovery was executed successfully.
Stop when the contract is unknown
A release accepts exactly release, reads and writes. Supported schemas are one and two; duplicate read lists and a write schema absent from readable support are rejected. Data schema must be a permitted integer. Unknown input is not interpreted as latest or assumed compatible. Unsupported scope remains visible as rejection or an error.
This simplification cannot express every upgrade path. Feature capabilities, other stores and delayed background work are absent. A real service must model the affected responsibilities in greater detail. The bounded comparison should not be described as calculating all risk in an operational release.
Rehearse the actual return separately
Local tests verify old-code/new-data blocking, read-only access by a bridge release and writable access when schemas agree. Recorded results keep executed false. No website release is downgraded and no operational data is restored by this experiment.
Real adoption requires retaining the exact code bundle and data backup, then exercising reads and necessary business flows in a separate environment. Operational action should follow that evidence and a fresh check of current data. I share a criterion for asking whether returned code understands present data, keeping code and data as a pair instead of treating a rollback button as sufficient proof.