Renames, one-way settings, firewall-blocked auth and decommissioning, each with the check that kept it safe
Database changes are where a Terraform mistake hurts most: replacements are slow, some settings can't be undone, and one wrong plan can destroy data. These four changes each came with a specific check that kept them safe.
| Change | What I did | The check that mattered |
|---|---|---|
| Instance rename | Destroy/recreate under new names, with new private endpoints and DNS records. Push runs plan only, and apply runs on manual dispatch | Recovered partial applies after CI token expiry by importing or deleting orphans |
| Update policy | Released a module version that exposes the policy, and confirmed a no-change plan before opting in | Flagged that the target policy is one-way and asked the requester to confirm it was needed |
| Entra auth for SQL VMs | Used firewall logs to show the hub firewall was denying graph.microsoft.com | Proposed one scoped FQDN rule instead of a broad allow |
| Decommission (one env) | count / for_each gated on environment, plus moved blocks | The plan showed a handful of destroys. A run with the pipeline's "enable destroy" option planned dozens, so that option was never used |
locals {
copy_enabled = var.environment != "uat"
}
resource "azurerm_storage_account" "copy" {
count = local.copy_enabled ? 1 : 0
# ...
}
moved {
from = azurerm_storage_account.copy
to = azurerm_storage_account.copy[0]
}
One request asked for new IP groups and a firewall rule between an app and its database. Checking it against the real network showed:
0.0.0.0/0 to the firewall, so the rule would never see that traffic.I raised all three with the requester before opening any networking PRs.
Safe database infrastructure isn't about avoiding change. It's about knowing exactly what each change will do, and stopping to ask when the answer can't be undone.
About this case study: this write-up is drawn from my hands-on platform engineering experience. Organisation names, system names, figures and timelines have been changed or generalised, and all code, configuration and queries are illustrative examples written for this page.