AWS Backup: Centralized Backup Policy Across Every Service in Your Account

Most AWS accounts have backup configured differently for every service. RDS automated backups set to 7 days. EBS snapshots on an EventBridge schedule someone wrote two years ago. DynamoDB point-in-time recovery enabled on some tables and not others. EFS backups toggled on during the initial setup and never reviewed since. Each of these is independent, audited separately, and easy to overlook during a recovery scenario.

AWS Backup consolidates all of this into a single policy-driven service. You define backup plans with schedules and retention rules. You assign resource types or specific resources to those plans. AWS Backup executes the backups, stores them in a vault, and gives you a compliance view showing which resources are protected and which are not. In this article I will walk through a production backup configuration with Terraform.

Backup Vaults

A backup vault is the storage container for recovery points. You create one per environment and optionally a separate vault for long-term retention. Vaults are encrypted with KMS and can be protected with a vault lock policy that prevents deletion of backups before they expire.

resource "aws_backup_vault" "production" {
  name        = "production-backup-vault"
  kms_key_arn = aws_kms_key.backup.arn

  tags = {
    Environment = "production"
    ManagedBy   = "terraform"
  }
}

resource "aws_backup_vault" "longterm" {
  name        = "longterm-backup-vault"
  kms_key_arn = aws_kms_key.backup.arn

  tags = {
    Environment = "production"
    Purpose     = "long-term-retention"
  }
}

resource "aws_backup_vault_lock_configuration" "production" {
  backup_vault_name   = aws_backup_vault.production.name
  min_retention_days  = 7
  max_retention_days  = 365
  changeable_for_days = 3
}

Vault lock with changeable_for_days = 3 gives you a 3-day window after enabling to change or remove the lock. After that window closes, the lock is permanent and no one, including the root account, can delete recovery points before their minimum retention period expires. This is the compliance control that satisfies audit requirements for backup immutability.

Backup Plans

resource "aws_backup_plan" "production" {
  name = "production-backup-plan"

  rule {
    rule_name         = "daily-backups"
    target_vault_name = aws_backup_vault.production.name
    schedule          = "cron(0 5 * * ? *)"
    start_window      = 60
    completion_window = 180

    lifecycle {
      delete_after = 35
    }

    copy_action {
      destination_vault_arn = "arn:aws:backup:eu-west-1:${data.aws_caller_identity.current.account_id}:backup-vault:dr-vault"

      lifecycle {
        delete_after = 35
      }
    }
  }

  rule {
    rule_name         = "weekly-backups"
    target_vault_name = aws_backup_vault.production.name
    schedule          = "cron(0 5 ? * SUN *)"
    start_window      = 60
    completion_window = 360

    lifecycle {
      delete_after = 90
    }

    copy_action {
      destination_vault_arn = aws_backup_vault.longterm.arn

      lifecycle {
        delete_after = 365
      }
    }
  }

  rule {
    rule_name         = "monthly-backups"
    target_vault_name = aws_backup_vault.longterm.name
    schedule          = "cron(0 5 1 * ? *)"
    start_window      = 60
    completion_window = 480

    lifecycle {
      delete_after = 2555
    }
  }

  tags = { ManagedBy = "terraform" }
}

The copy_action to eu-west-1 creates a cross-region copy of every daily backup. If your primary region has an outage, recovery points exist in the DR region. This is the most important backup configuration decision for production: backups in the same region as your data are not true disaster recovery.

The three-tier schedule covers the most common compliance requirements. Daily backups with 35-day retention cover operational recovery from accidental deletion or corruption. Weekly backups with 90-day retention support investigations that surface weeks after an incident. Monthly backups with 7-year retention satisfy most regulatory requirements for financial and healthcare data.

Resource Assignments

resource "aws_backup_selection" "production_databases" {
  name         = "production-databases"
  plan_id      = aws_backup_plan.production.id
  iam_role_arn = aws_iam_role.backup.arn

  resources = [
    "arn:aws:rds:*:*:db:*",
    "arn:aws:rds:*:*:cluster:*",
    "arn:aws:dynamodb:*:*:table/*",
    "arn:aws:elasticfilesystem:*:*:file-system/*"
  ]

  condition {
    string_equals {
      key   = "aws:ResourceTag/Environment"
      value = "production"
    }

    string_equals {
      key   = "aws:ResourceTag/BackupEnabled"
      value = "true"
    }
  }
}

resource "aws_backup_selection" "production_volumes" {
  name         = "production-ebs-volumes"
  plan_id      = aws_backup_plan.production.id
  iam_role_arn = aws_iam_role.backup.arn

  resources = ["arn:aws:ec2:*:*:volume/*"]

  condition {
    string_equals {
      key   = "aws:ResourceTag/Environment"
      value = "production"
    }
  }
}

Using tag-based selection with BackupEnabled = true gives you explicit opt-in control. A resource is only backed up when it has both the Environment = production tag and the BackupEnabled = true tag. This prevents newly created resources from automatically entering the backup plan before someone verifies they should be there, while also making it easy to add resources to backup coverage by adding a tag.

Backup Compliance Monitoring

resource "aws_backup_framework" "production" {
  name        = "production-backup-compliance"
  description = "Compliance framework for production backup requirements"

  control {
    name = "BACKUP_PLAN_MIN_FREQUENCY_AND_MIN_RETENTION_CHECK"
    input_parameter {
      name  = "requiredFrequencyUnit"
      value = "days"
    }
    input_parameter {
      name  = "requiredFrequencyValue"
      value = "1"
    }
    input_parameter {
      name  = "requiredRetentionDays"
      value = "35"
    }
  }

  control {
    name = "BACKUP_RECOVERY_POINT_ENCRYPTED"
  }

  control {
    name = "BACKUP_RECOVERY_POINT_MINIMUM_RETENTION_CHECK"
    input_parameter {
      name  = "requiredRetentionDays"
      value = "35"
    }
  }

  control {
    name = "BACKUP_RESOURCES_PROTECTED_BY_CROSS_REGION"
    input_parameter {
      name  = "crossRegionList"
      value = "eu-west-1"
    }
  }
}

resource "aws_cloudwatch_metric_alarm" "backup_job_failed" {
  alarm_name          = "backup-job-failed"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 1
  metric_name         = "NumberOfBackupJobsFailed"
  namespace           = "AWS/Backup"
  period              = 86400
  statistic           = "Sum"
  threshold           = 0
  alarm_description   = "One or more backup jobs failed in the last 24 hours"
  alarm_actions       = [aws_sns_topic.alerts.arn]
}

The backup framework runs continuous compliance checks and surfaces resources that violate your backup policies. The BACKUP_RESOURCES_PROTECTED_BY_CROSS_REGION control flags any resource that does not have a backup copy in your DR region. Review the compliance report weekly. Resources that appear in the non-compliant list are either missing their backup tags or have been created recently and not yet added to the backup selection.

Closing Thoughts

AWS Backup eliminates the patchwork of service-specific backup configurations that most accounts accumulate. A single plan, tag-based selection, cross-region copies, and vault lock give you a backup posture that satisfies most compliance requirements and gives you real confidence in your recovery capability.

Test your restores. A backup you have never restored from is a backup you do not actually have. Schedule quarterly restore tests for your critical databases and document the recovery time. When you need that recovery in production, you want to have done it before under calm conditions.

Enjoy the cloud.

Osama


#AWS #AWSBackup #DisasterRecovery #CloudArchitecture #Terraform #InfrastructureAsCode #CloudSecurity #AmazonWebServices #SolutionsArchitect #CloudComputing #DataProtection #BackupCompliance #CloudGovernance #TechBlog #CloudInfrastructure #RDS #DynamoDB #EFS #BusinessContinuity #DevOps

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.