Infrastructure as code Required
Protect resources that hold data
Turn on deletion protection for every database, bucket and disk that holds data. Stop any plan that deletes or replaces one until a second person approves.
How to do it
Set the provider's own protection, such as deletion_protection on databases, and prevent_destroy in the code. A renamed resource or a changed setting can mean "destroy and create", which loses the data. Read the plan as JSON in CI, and fail it when a protected type has delete among its actions. Backups are a separate safety net, as in the operations playbook.
Example
resource "aws_db_instance" "orders" {
identifier = "shop-orders"
deletion_protection = true
lifecycle {
prevent_destroy = true
}
}
// node check-plan.mjs plan.json, after: tofu show -json release.tfplan > plan.json
import { readFileSync } from 'node:fs';
const PROTECTED_TYPES = new Set(['aws_db_instance', 'aws_s3_bucket', 'aws_ebs_volume']);
const plan = JSON.parse(readFileSync(process.argv[2], 'utf8'));
const losses = plan.resource_changes.filter(change => PROTECTED_TYPES.has(change.type) && change.change.actions.includes('delete'));
for (const change of losses) console.error(`Would delete ${change.address}`);
process.exit(losses.length ? 1 : 0);
# python check_plan.py plan.json
import json, sys
PROTECTED_TYPES = {"aws_db_instance", "aws_s3_bucket", "aws_ebs_volume"}
plan = json.load(open(sys.argv[1]))
losses = [c for c in plan["resource_changes"] if c["type"] in PROTECTED_TYPES and "delete" in c["change"]["actions"]]
for change in losses:
print(f"Would delete {change['address']}", file=sys.stderr)
sys.exit(1 if losses else 0)
How to check
Change a database's name in a branch. The CI plan step fails and names the resource. In the cloud, a delete call on the production database is refused.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers infrastructure playbook: https://agentwranglers.se/playbook/infrastructure/infrastructure-as-code/protect-stateful-resources.