Zero-downtime deployment means two versions of your app run at the same time. Rolling updates, canary releases, and blue-green deployments all work that way. The old version keeps serving traffic while the new one starts, so for a few seconds, or a few minutes, both versions talk to the same database.
That window is where the damage happens, and the deployment strategy that sold you the zero downtime says nothing about it.
I learned this at a day job. We dropped a column in the same deploy as the code that stopped using it, and the alert fired while the rollout was still running.
The column you deleted
Dropping a column is usually one deployment. The migration removes the column, the new code stops selecting it, and both changes ship together. It works on your laptop.
In production the rollout is gradual. The migration runs, then some replicas serve the new version while others still run the old one. The old code selects a column that no longer exists. It throws on every request it handles, and the error rate spikes until the last replica turns over.
Rollback is gone too. The old version cannot run against the new schema, so the only way out is forward, at the worst possible moment.
Two deployments, not one
Phase one deploys code that no longer uses the column. The column still exists, so the old version and the new version both run without errors. Rollback works the whole time, because either version is happy with the schema in front of it.
Phase two, once the first is settled, deletes the column.
The gap between them is the point.
It is not only about columns
Renaming a field, changing a type, splitting a table, moving data to a new home. Every schema change has the same shape. Expand the schema so both versions work. Migrate. Then contract, once nothing reads the old shape.
Zero-downtime deployment buys you a window where two versions of your code share one database. Two phases is how you survive it.