Our longest serving production database was created by hand in a console in 2019, by an engineer who has since left, and it was the last thing in that account with no code behind it. I imported it on a Tuesday. Write the resource block, run the import, read the plan. That plan is the entire value of an import: it tells you whether the code you just wrote describes the thing that already exists.
Mine proposed six changes and I applied them.
I had written the block by copying the module every other database in the estate uses and filling in the name, the instance class and the engine version. The module is opinionated, which is why we like it. It sets a backup retention of seven days, an enhanced monitoring interval of sixty seconds, a standard parameter group, and deletion protection from a variable that defaults to off outside production. The database I was importing had thirty five days of retention, one second monitoring, a parameter group with a hand tuned work_mem and shared buffer setting, and deletion protection on. Somebody had chosen every one of those deliberately, years ago, for reasons recorded nowhere.
In the plan those six lines read as drift. That word carries an assumption inside it: that the code is the intention and the running system is the accident. During an import it is exactly backwards. The running system is four years of operational decisions and the code is something I typed that morning.
The retention change went unnoticed until three weeks later, when we wanted a point in time restore to a day that no longer existed. The parameter group was worse in a quieter way, because a static parameter needs a reboot, so it sat pending until the maintenance window that Sunday and the query plans changed at two in the morning with no change record anywhere near it.
We import differently now. The first apply after an import must propose nothing at all, which means writing the resource from a description of the live object and moving it onto the module afterwards as its own reviewed change. Every setting that differed from our defaults was written down with the reason we could reconstruct for it.
An import is not the moment your code takes charge. It is the moment you learn what you were about to replace.
– Sergey Shinder
Top comments (0)