---
title: Low RDS backup retention period
description: Datadog, the leading service for cloud-scale monitoring.
breadcrumbs: >-
  Docs > Datadog Security > Code Security > Infrastructure as Code (IaC)
  Security > IaC Security Rules > Low RDS backup retention period
---

# Low RDS backup retention period

{% callout %}
# Important note for users on the following Datadog sites: app.ddog-gov.com, us2.ddog-gov.com

{% alert level="danger" %}
This product is not supported for your selected [Datadog site](https://docs.datadoghq.com/getting_started/site.md). ({% placeholder "user-datadog-site-name" /%}).
{% /alert %}

{% /callout %}

## Metadata{% #metadata %}

**Id:** `cloudformation-aws-low-rds-backup-retention-period` 

**Provider:** AWS

**Platform:** CloudFormation

**Severity:** Low

**Category:** Backup

#### Learn More{% #learn-more %}

- [Provider Reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html)

### Description{% #description %}

RDS clusters and standalone instances must retain automated backups for at least `7` days to ensure recoverability and limit data loss from accidental deletion, corruption, or operational errors. In AWS CloudFormation, the `BackupRetentionPeriod` property on `AWS::RDS::DBCluster` (and on standalone `AWS::RDS::DBInstance` resources) must be defined and set to `7` or greater. This rule flags `AWS::RDS::DBCluster` resources that omit `BackupRetentionPeriod` or set it to a value less than `7`. For `AWS::RDS::DBInstance` resources, the check is enforced only when no `AWS::RDS::DBCluster` resources are defined in the template because cluster-level backup retention may govern recovery for clustered deployments. Resources missing the property or with `BackupRetentionPeriod` less than `7` will be reported.

Secure configuration examples:

```yaml
MyDBCluster:
  Type: AWS::RDS::DBCluster
  Properties:
    Engine: aurora-mysql
    BackupRetentionPeriod: 7
```

```yaml
MyDBInstance:
  Type: AWS::RDS::DBInstance
  Properties:
    DBInstanceClass: db.t3.medium
    Engine: mysql
    BackupRetentionPeriod: 7
```

## Compliant Code Examples{% #compliant-code-examples %}

```yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: Creates RDS Cluster
Parameters:
  PMDatabaseEngine:
    Type: String
    Default: "MySQL"
    Description: "Database engine, Aurora, MySQL or PostgreSQL"
  PMRDSSG:
    Description: "Select the Security Group to use for the ELB"
    Type: "AWS::EC2::SecurityGroup::Id"
  PMDatabaseEngineVer:
    Type: String
    Description: "Database engine ver"
  PMDatabaseUsername:
    NoEcho: 'true'
    Type: String
    Description: "Database admin account name"
  PMDatabasePassword:
    NoEcho: 'true'
    Type: String
    Description: "Database admin account password"
  PMDBClusterParameterGroupName:
    Description: "Db Parameter Groupname"
    Type: String
  PMDatabaseInstanceClass:
    Type: String
    Default: "db.t2.micro"
    Description: "Database instance class"
  PMPrivateSubnets:
    Description: "Subnets to launch instances into"
    Type: "List<AWS::EC2::Subnet::Id>"
  PMServerEnv:
    Description: "Server Environment name."
    ConstraintDescription: "Choose an Environment from the drop down"
    Type: String
  PMDBClusterIdentifier:
    Description: "Db Cluster Name."
    Type: String

Resources:
  DatabaseCluster:
    Type: "AWS::RDS::DBCluster"
    Properties:
      VpcSecurityGroupIds:
      - Ref: "PMRDSSG"
      Engine: !Ref "PMDatabaseEngine"
      EngineVersion: !Ref "PMDatabaseEngineVer"
      MasterUsername: !Ref "PMDatabaseUsername"
      MasterUserPassword: !Ref "PMDatabasePassword"
      DBClusterParameterGroupName: !Ref "RDSDBClusterParameterGroup"
      StorageEncrypted: true
      BackupRetentionPeriod: 16
      PreferredBackupWindow: '12:00-13:00'
      PreferredMaintenanceWindow: 'mon:13:00-mon:14:00'

  Database1:
    Type: "AWS::RDS::DBInstance"
    Properties:
      Engine: !Ref "PMDatabaseEngine"
      DBClusterIdentifier: !Ref "DatabaseCluster"
      DBInstanceClass: !Ref "PMDatabaseInstanceClass"
      DBSubnetGroupName: !Ref "DbSubnetGroup"
      DBInstanceIdentifier: !Sub "${PMDBClusterIdentifier}-db1"

  Database2:
    Type: "AWS::RDS::DBInstance"
    Properties:
      Engine: !Ref "PMDatabaseEngine"
      DBClusterIdentifier: !Ref "DatabaseCluster"
      DBInstanceClass: !Ref "PMDatabaseInstanceClass"
      DBSubnetGroupName: !Ref "DbSubnetGroup"
      DBInstanceIdentifier: !Sub "${PMDBClusterIdentifier}-db2"

  DbSubnetGroup:
    Type: "AWS::RDS::DBSubnetGroup"
    Properties:
      DBSubnetGroupDescription: !Sub "${PMServerEnv} RDS DB subnet group"
      SubnetIds:
        Ref: "PMPrivateSubnets"

  RDSDBClusterParameterGroup:
    Type: "AWS::RDS::DBClusterParameterGroup"
    Properties:
      Description: "CloudFormation Sample Aurora Cluster Parameter Group"
      Family: !Ref "PMDBClusterParameterGroupName"
      Parameters:
        time_zone: "UTC"
        collation_connection: "utf8_general_ci"
        character_set_database: "utf8"

Outputs:
  RdsDbId:
    Description: "RDS Database Cluster ID"
    Value: !Ref "DatabaseCluster"
  RdsEndpointAdd:
    Description: "RDS Database Endpoint"
    Value: !GetAtt "DatabaseCluster.Endpoint.Address"
  RdsReadEndpointAdd:
    Description: "RDS Read Database Endpoint"
    Value: !GetAtt "DatabaseCluster.ReadEndpoint.Address"
  RdsEndpointPort:
    Description: "RDS Database Port"
    Value: !GetAtt "DatabaseCluster.Endpoint.Port"
  DbUser:
    Description: "RDS Database admin account user"
    Value: !Ref "PMDatabaseUsername"
  DbPassword:
    Description: "RDS Database admin account password"
    Value: !Ref "PMDatabasePassword"
```

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: RDS Storage Encrypted
Parameters:
  SourceDBInstanceIdentifier:
    Type: String
  DBInstanceType:
    Type: String
  SourceRegion:
    Type: String
Resources:
  MyKey:
    Type: "AWS::KMS::Key"
    Properties:
      KeyPolicy:
        Version: 2012-10-17
        Id: key-default-1
        Statement:
          - Sid: Enable IAM User Permissions
            Effect: Allow
            Principal:
              AWS: !Join
                - ""
                - - "arn:aws:iam::"
                  - !Ref "AWS::AccountId"
                  - ":root"
            Action: "kms:*"
            Resource: "*"
  MyDBSmall:
    Type: "AWS::RDS::DBInstance"
    Properties:
      DBInstanceClass: !Ref DBInstanceType
      SourceDBInstanceIdentifier: !Ref SourceDBInstanceIdentifier
      SourceRegion: !Ref SourceRegion
      KmsKeyId: !Ref MyKey
      BackupRetentionPeriod: 7
Outputs:
  InstanceId:
    Description: InstanceId of the newly created RDS Instance
    Value: !Ref MyDBSmall
```

```yaml
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  DBUser:
    NoEcho: true
    Description: The database admin account username
    Type: String
    MinLength: 1
    MaxLength: 16
    AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*"
    ConstraintDescription: must begin with a letter and contain only alphanumeric characters.
  DBPassword:
    NoEcho: true
    Description: The database admin account password
    Type: String
    MinLength: 1
    MaxLength: 41
    AllowedPattern: "[a-zA-Z0-9]*"
    ConstraintDescription: must contain only alphanumeric characters.
Resources:
  MyDB:
    Type: "AWS::RDS::DBInstance"
    Properties:
      AllocatedStorage: '5'
      DBInstanceClass: db.t2.small
      Engine: MySQL
      EngineVersion: '5.5'
      MasterUsername: !Ref DBUser
      MasterUserPassword: !Ref DBPassword
      DBParameterGroupName: !Ref MyRDSParamGroup
      BackupRetentionPeriod: 10
  MyRDSParamGroup:
    Type: "AWS::RDS::DBParameterGroup"
    Properties:
      Family: MySQL5.5
      Description: CloudFormation Sample Database Parameter Group
      Parameters:
        autocommit: '1'
        general_log: '1'
        old_passwords: '0'
```

## Non-Compliant Code Examples{% #non-compliant-code-examples %}

```yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: Creates RDS Cluster
Parameters:
  PMDatabaseEngine:
    Type: String
    Default: "MySQL"
    Description: "Database engine, Aurora, MySQL or PostgreSQL"
  PMRDSSG:
    Description: "Select the Security Group to use for the ELB"
    Type: "AWS::EC2::SecurityGroup::Id"
  PMDatabaseEngineVer:
    Type: String
    Description: "Database engine ver"
  PMDatabaseUsername:
    NoEcho: 'true'
    Type: String
    Description: "Database admin account name"
  PMDatabasePassword:
    NoEcho: 'true'
    Type: String
    Description: "Database admin account password"
  PMDBClusterParameterGroupName:
    Description: "Db Parameter Groupname"
    Type: String
  PMDatabaseInstanceClass:
    Type: String
    Default: "db.t2.micro"
    Description: "Database instance class"
  PMPrivateSubnets:
    Description: "Subnets to launch instances into"
    Type: "List<AWS::EC2::Subnet::Id>"
  PMServerEnv:
    Description: "Server Environment name."
    ConstraintDescription: "Choose an Environment from the drop down"
    Type: String
  PMDBClusterIdentifier:
    Description: "Db Cluster Name."
    Type: String

Resources:
  DatabaseCluster:
    Type: "AWS::RDS::DBCluster"
    Properties:
      VpcSecurityGroupIds:
      - Ref: "PMRDSSG"
      Engine: !Ref "PMDatabaseEngine"
      EngineVersion: !Ref "PMDatabaseEngineVer"
      MasterUsername: !Ref "PMDatabaseUsername"
      MasterUserPassword: !Ref "PMDatabasePassword"
      DBClusterParameterGroupName: !Ref "RDSDBClusterParameterGroup"
      StorageEncrypted: true
      BackupRetentionPeriod: 3
      PreferredBackupWindow: '12:00-13:00'
      PreferredMaintenanceWindow: 'mon:13:00-mon:14:00'

  Database1:
    Type: "AWS::RDS::DBInstance"
    Properties:
      Engine: !Ref "PMDatabaseEngine"
      DBClusterIdentifier: !Ref "DatabaseCluster"
      DBInstanceClass: !Ref "PMDatabaseInstanceClass"
      DBSubnetGroupName: !Ref "DbSubnetGroup"
      DBInstanceIdentifier: !Sub "${PMDBClusterIdentifier}-db1"

  Database2:
    Type: "AWS::RDS::DBInstance"
    Properties:
      Engine: !Ref "PMDatabaseEngine"
      DBClusterIdentifier: !Ref "DatabaseCluster"
      DBInstanceClass: !Ref "PMDatabaseInstanceClass"
      DBSubnetGroupName: !Ref "DbSubnetGroup"
      DBInstanceIdentifier: !Sub "${PMDBClusterIdentifier}-db2"

  DbSubnetGroup:
    Type: "AWS::RDS::DBSubnetGroup"
    Properties:
      DBSubnetGroupDescription: !Sub "${PMServerEnv} RDS DB subnet group"
      SubnetIds:
        Ref: "PMPrivateSubnets"

  RDSDBClusterParameterGroup:
    Type: "AWS::RDS::DBClusterParameterGroup"
    Properties:
      Description: "CloudFormation Sample Aurora Cluster Parameter Group"
      Family: !Ref "PMDBClusterParameterGroupName"
      Parameters:
        time_zone: "UTC"
        collation_connection: "utf8_general_ci"
        character_set_database: "utf8"

Outputs:
  RdsDbId:
    Description: "RDS Database Cluster ID"
    Value: !Ref "DatabaseCluster"
  RdsEndpointAdd:
    Description: "RDS Database Endpoint"
    Value: !GetAtt "DatabaseCluster.Endpoint.Address"
  RdsReadEndpointAdd:
    Description: "RDS Read Database Endpoint"
    Value: !GetAtt "DatabaseCluster.ReadEndpoint.Address"
  RdsEndpointPort:
    Description: "RDS Database Port"
    Value: !GetAtt "DatabaseCluster.Endpoint.Port"
  DbUser:
    Description: "RDS Database admin account user"
    Value: !Ref "PMDatabaseUsername"
  DbPassword:
    Description: "RDS Database admin account password"
    Value: !Ref "PMDatabasePassword"
```

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: RDS Storage Encrypted
Parameters:
  SourceDBInstanceIdentifier:
    Type: String
  DBInstanceType:
    Type: String
  SourceRegion:
    Type: String
Resources:
  MyKey:
    Type: "AWS::KMS::Key"
    Properties:
      KeyPolicy:
        Version: 2012-10-17
        Id: key-default-1
        Statement:
          - Sid: Enable IAM User Permissions
            Effect: Allow
            Principal:
              AWS: !Join
                - ""
                - - "arn:aws:iam::"
                  - !Ref "AWS::AccountId"
                  - ":root"
            Action: "kms:*"
            Resource: "*"
  MyDBSmall:
    Type: "AWS::RDS::DBInstance"
    Properties:
      DBInstanceClass: !Ref DBInstanceType
      SourceDBInstanceIdentifier: !Ref SourceDBInstanceIdentifier
      SourceRegion: !Ref SourceRegion
      KmsKeyId: !Ref MyKey
      BackupRetentionPeriod: 6
Outputs:
  InstanceId:
    Description: InstanceId of the newly created RDS Instance
    Value: !Ref MyDBSmall
```

```yaml
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  DBUser:
    NoEcho: true
    Description: The database admin account username
    Type: String
    MinLength: 1
    MaxLength: 16
    AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*"
    ConstraintDescription: must begin with a letter and contain only alphanumeric characters.
  DBPassword:
    NoEcho: true
    Description: The database admin account password
    Type: String
    MinLength: 1
    MaxLength: 41
    AllowedPattern: "[a-zA-Z0-9]*"
    ConstraintDescription: must contain only alphanumeric characters.
Resources:
  MyDB:
    Type: "AWS::RDS::DBInstance"
    Properties:
      AllocatedStorage: '5'
      DBInstanceClass: db.t2.small
      Engine: MySQL
      EngineVersion: '5.5'
      MasterUsername: !Ref DBUser
      MasterUserPassword: !Ref DBPassword
      DBParameterGroupName: !Ref MyRDSParamGroup
  MyRDSParamGroup:
    Type: "AWS::RDS::DBParameterGroup"
    Properties:
      Family: MySQL5.5
      Description: CloudFormation Sample Database Parameter Group
      Parameters:
        autocommit: '1'
        general_log: '1'
        old_passwords: '0'
```
