The schema had to change. A new column would solve it, but the clock was ticking and the deployment window was small. You open the migration file and define the column with precision—type, nullability, defaults. Once committed, it will alter every row in production. There’s no room for error.
Adding a new column is simple in theory. In practice, the work spans the database, application code, and API contracts. The database migration must be backward-compatible so you can deploy without downtime. This means creating the column first, leaving it unused until all code is ready. Only then should you write to it. Then backfill carefully, avoiding locks that can stall the system.
Use explicit types. Store booleans as BOOLEAN, timestamps as TIMESTAMP WITH TIME ZONE, and never overload a field for multiple meanings. Set sane defaults to prevent null-related bugs. If you must store JSON, validate it at the application layer before insert.