The Problem
You open the AWS Backup Jobs Dashboard and see:
- 168 completed jobs
- 112 failed jobs
- Failure reason: Access denied
- Affected resource type: S3
Meanwhile, your EBS snapshots page shows 195 snapshots you cannot delete because they are βmanaged by AWS Backup.β Your Backup plan is working for EC2 but failing for S3 β every single day.
This is one of the most common AWS Backup misconfigurations, and it stems from a single missing IAM policy.
Root Cause: Missing S3 Backup Permissions
When you create a Backup plan that includes S3 buckets, the Backup service role needs specific S3 permissions beyond what the default role provides. The default AWSBackupDefaultServiceRole often ships with EC2/EBS permissions but not S3.
The daily pattern looks like this:
03:00 UTC β Backup plan triggers
β
EC2 AMI backup β Creates snapshot β Completed
β S3 backup β Access Denied β FailedFix 1: Add S3 Backup Permissions to the IAM Role
Find Your Backup Role
# List backup plans
aws backup list-backup-plans \
--query "BackupPlansList[].{Name:BackupPlanName,ID:BackupPlanId}" \
--output table
# Get the plan details (shows the IAM role ARN)
aws backup get-backup-selection \
--backup-plan-id <your-plan-id> \
--selection-id <your-selection-id>Or in the Console: AWS Backup β Backup plans β your plan β Resource assignments β IAM role
Attach the S3 Backup Policy
# Attach the AWS managed policy for S3 backups
aws iam attach-role-policy \
--role-name AWSBackupDefaultServiceRole \
--policy-arn arn:aws:iam::aws:policy/AWSBackupServiceRolePolicyForS3BackupThis policy grants:
s3:GetBucketTaggings3:GetInventoryConfigurations3:ListBucketVersionss3:ListBuckets3:GetBucketVersionings3:GetBucketLocations3:GetBucketAcls3:PutInventoryConfigurations3:GetBucketNotifications3:PutBucketNotifications3:GetObject/s3:GetObjectVersion/s3:GetObjectAcl
Also Attach the S3 Restore Policy
If you ever need to restore from S3 backups:
aws iam attach-role-policy \
--role-name AWSBackupDefaultServiceRole \
--policy-arn arn:aws:iam::aws:policy/AWSBackupServiceRolePolicyForS3RestoreFix 2: Remove S3 If You Donβt Need It
If you never intended to back up S3 buckets:
# List resource assignments in your backup plan
aws backup list-backup-selections \
--backup-plan-id <your-plan-id>
# Update the selection to exclude S3
# Or in Console: Backup plans β Edit resource assignment β remove S3In the Console: Backup plans β your plan β Resource assignments β Edit β Remove S3 resource type
Clean Up Backup-Managed Snapshots
EBS snapshots created by AWS Backup cannot be deleted from the EC2 Console. You must delete the recovery points from the Backup Vault.
Console Method
- AWS Backup β Vaults β select your vault (usually βDefaultβ)
- Filter by Resource type: EC2 or search by resource ID
i-0a30bab507a1adaf5 - Select the old recovery points you want to remove
- Actions β Delete
CLI Method (Bulk)
VAULT_NAME="Default"
# List all recovery points in the vault
aws backup list-recovery-points-by-backup-vault \
--backup-vault-name "$VAULT_NAME" \
--query "RecoveryPoints[?ResourceType=='EC2'].{ARN:RecoveryPointArn,Created:CreationDate,Resource:ResourceArn}" \
--output table
# Delete recovery points older than 14 days
CUTOFF=$(date -d '14 days ago' +%Y-%m-%dT%H:%M:%S 2>/dev/null || date -v-14d +%Y-%m-%dT%H:%M:%S)
aws backup list-recovery-points-by-backup-vault \
--backup-vault-name "$VAULT_NAME" \
--query "RecoveryPoints[?CreationDate<'$CUTOFF' && ResourceType=='EC2'].RecoveryPointArn" \
--output text | tr '\t' '\n' | while read arn; do
echo "Deleting: $arn"
aws backup delete-recovery-point \
--backup-vault-name "$VAULT_NAME" \
--recovery-point-arn "$arn"
sleep 0.5 # Avoid throttling
doneOnce recovery points are deleted, the associated EBS snapshots are automatically released and removed.
Fix Retention to Prevent Future Accumulation
Your current setup retains 40+ days of daily snapshots. If you only need 7 or 14 days:
Console
Backup plans β your plan β Edit rule β Retention period β 14 days
CLI
# Update the backup rule with a 14-day retention
aws backup update-backup-plan \
--backup-plan-id <your-plan-id> \
--backup-plan '{
"BackupPlanName": "DailyBackup",
"Rules": [{
"RuleName": "DailyRule",
"TargetBackupVaultName": "Default",
"ScheduleExpression": "cron(0 3 * * ? *)",
"StartWindowMinutes": 60,
"CompletionWindowMinutes": 180,
"Lifecycle": {
"DeleteAfterDays": 14
}
}]
}'Storage Cost Impact
Each 8 GiB daily snapshot (incremental) costs roughly:
Incremental size: ~0.5-2 GiB/day (typical for OS volume)
At $0.05/GB-month:
14-day retention: ~$0.50-2.00/month
40-day retention: ~$1.50-5.00/month
195 snapshots (current): ~$10-40/monthNot catastrophic, but unnecessary cost that compounds.
Handle the One AMI-Linked Snapshot
One snapshot (snap-0d09b71f596d91e71) is tied to AMI ami-020b2f4148cc60cc8 (created September 2025). This is NOT Backup-managed β it was a manual CreateImage call.
# Check if any instance still uses this AMI
aws ec2 describe-instances \
--filters "Name=image-id,Values=ami-020b2f4148cc60cc8" \
--query "Reservations[].Instances[].InstanceId" \
--output text
# If empty (no instances), safe to deregister
aws ec2 deregister-image --image-id ami-020b2f4148cc60cc8
# Now delete the snapshot
aws ec2 delete-snapshot --snapshot-id snap-0d09b71f596d91e71Complete Cleanup Checklist
| Step | Action | Where |
|---|---|---|
| 1 | Fix IAM: attach AWSBackupServiceRolePolicyForS3Backup | IAM Console |
| 2 | Or remove S3 from Backup plan resource assignments | Backup Console |
| 3 | Delete old recovery points from vault | Backup β Vaults |
| 4 | Set retention to 14 days in Backup rule | Backup β Plans |
| 5 | Deregister AMI ami-020b2f4148cc60cc8 | EC2 β AMIs |
| 6 | Delete orphaned snapshot snap-0d09b71f596d91e71 | EC2 β Snapshots |
| 7 | Verify next day: 0 failed jobs | Backup β Jobs Dashboard |
Monitor Going Forward
Set a CloudWatch alarm for Backup job failures:
aws cloudwatch put-metric-alarm \
--alarm-name "BackupJobFailures" \
--metric-name "NumberOfBackupJobsFailed" \
--namespace "AWS/Backup" \
--statistic Sum \
--period 86400 \
--threshold 1 \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--alarm-actions arn:aws:sns:us-east-1:025066287134:alerts