How we handled a database migration without downtime
The migration looked small on paper: add a few columns, backfill old records, then switch the application to read the new shape. The risk was that the table was hot all day and the old worker code would still be running during deploy. We broke it into three releases. First release added nullable columns and wrote both old and new fields. Second release backfilled in chunks during low traffic, wit…