In a Continuous Deployment/Continuous Integration (CD/CI) world, most commentary dances around references to database changes as being a bottleneck, hard, awkward, or even painful. The reasoning supporting this perspective of suffering seems to arise from a desire for all changes to be fairly isolated matters. After all, a new function within an API, driving a new behavior on a screen, can just slip in, start executing, and life continues. For those familiar with the old nursery rhyme “The Farmer in the Dell,” the line, “The cheese stands alone” is memorable as the end to the rhyme. All the previously mentioned rhyme characters have taken a partner along the way, the farmer, wife, child, nurse, cow, dog, cat, and mouse. CD/CI wishes for things to be like the cheese, alone, effectively plug-and-play. Unlike that farmer’s cheese, database changes do not stand alone.
Database changes have reasons driving the need for the change, and fulfilling the change is more than just, “here’s an altered structure.” The structure changes, by themselves, are largely meaningless. There are processes to be put in place to populate data for the new or changed structure and keep it fresh; plus, there are dashboards, reports, web pages, and more waiting for that change and its fresh data. For an operational solution, data may indeed be isolated to the single solution limiting the number of others involved; but once you have an ERP, a data warehouse, data marts, a data lake, you have resources shared across a significant population. There is a large audience that will see and may need to understand those changes. The database is the watering hole all the animals gather around. A database change is more of the evolution of an environment than it is an event happening in isolation.
Certainly, there are strategies that may be employed to allow for database changes to be cheesier than they might otherwise be. Changes that have no impact to already existing code are the cheesiest. These cheesy changes would be—new tables, new columns on tables, new views, or other similarly new objects. Being new, no existing code should break. This level of cheesiness assumes that code is properly written and does not include such bad practices as using “SELECT *” along the way, or possibly depending on a specific column to be in a specific position (3rd, 4th, etc.) within a table or view. These “new only” changes allow for database changes to move in without breaking existing code, and because of this, the new code using these objects can be implemented at any point down the road. Just make sure the code populating this data is implemented and executed prior to the code that wishes to use the data from those new structures.
Other kinds of database changes can be more destructive and cause existing code problems. These least cheesy changes include changing a data type, renaming a column or a table or a view, changing the grain of the data within a table by a primary key alteration, removing a column, and dropping a table or a view. These more destructive changes are highly correlated with all the existing processing using the structures involved. Not being cheesy does not mean these kinds of changes cannot be done, but it does mean they must be done cautiously. The caution needed means that the change to the database and the changes to impacted existing processes must be packaged together as a single change unit. And by default, having many things that must be changed at once, this means such a change is carrying greater risk to be managed and contained. I guess one might say, it isn’t easy being cheesy.