54

I have an RDS database instance on AWS and have turned it off for now. However, every few days it starts up on its own. I don't have any other services running right now.

There is this event in my RDS log: "DB instance is being started due to it exceeding the maximum allowed time being stopped."

Why is there a limit to how long my RDS instance can be stopped? I just want to put my project on hold for a few weeks, but AWS won't let me turn off my DB? It costs $12.50/mo to have it sit idle, so I don't want to pay for this, and I certainly don't want AWS starting an instance for me that does not get used.

Please help!

SH10151
  • 954
  • 1
  • 10
  • 17

1 Answers1

36

That's a limitation of this new feature.

You can stop an instance for up to 7 days at a time. After 7 days, it will be automatically started. For more details on stopping and starting a database instance, please refer to Stopping and Starting a DB Instance in the Amazon RDS User Guide.

You can setup a cron job to stop the instance again after 7 days. You can also change to a smaller instance size to save money.

Another option is the upcoming Aurora Serverless which stops and starts for you automatically. It might be more expensive than a dedicated instance when running 24/7.

Finally, there is always Heroku which gives you a free database instance that starts and stops itself with some limitations.


You can also try saving the following CloudFormation template as KeepDbStopped.yml and then deploy with this command:

aws cloudformation deploy --template-file KeepDbStopped.yml --stack-name stop-db --capabilities CAPABILITY_IAM --parameter-overrides DB=arn:aws:rds:us-east-1:XXX:db:XXX

Make sure to change arn:aws:rds:us-east-1:XXX:db:XXX to your RDS ARN.

Description: Automatically stop RDS instance every time it turns on due to exceeding the maximum allowed time being stopped
Parameters:
  DB:
    Description: ARN of database that needs to be stopped
    Type: String
    AllowedPattern: arn:aws:rds:[a-z0-9\-]+:[0-9]+:db:[^:]*
Resources:
  DatabaseStopperFunction:
    Type: AWS::Lambda::Function
    Properties:
      Role: !GetAtt DatabaseStopperRole.Arn
      Runtime: python3.6
      Handler: index.handler
      Timeout: 20
      Code:
        ZipFile:
          Fn::Sub: |
            import boto3
            import time

            def handler(event, context):
              print("got", event)
              db = event["detail"]["SourceArn"]
              id = event["detail"]["SourceIdentifier"]
              message = event["detail"]["Message"]
              region = event["region"]
              rds = boto3.client("rds", region_name=region)

              if message == "DB instance is being started due to it exceeding the maximum allowed time being stopped.":
                print("database turned on automatically, setting last seen tag...")
                last_seen = int(time.time())
                rds.add_tags_to_resource(ResourceName=db, Tags=[{"Key": "DbStopperLastSeen", "Value": str(last_seen)}])

              elif message == "DB instance started":
                print("database started (and sort of available?)")

                last_seen = 0
                for t in rds.list_tags_for_resource(ResourceName=db)["TagList"]:
                  if t["Key"] == "DbStopperLastSeen":
                    last_seen = int(t["Value"])

                if time.time() < last_seen + (60 * 20):
                  print("database was automatically started in the last 20 minutes, turning off...")
                  time.sleep(10)  # even waiting for the "started" event is not enough, so add some wait
                  rds.stop_db_instance(DBInstanceIdentifier=id)

                  print("success! removing auto-start tag...")
                  rds.add_tags_to_resource(ResourceName=db, Tags=[{"Key": "DbStopperLastSeen", "Value": "0"}])

                else:
                  print("ignoring manual database start")

              else:
                print("error: unknown database event!")
  DatabaseStopperRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Action:
              - sts:AssumeRole
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: Notify
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Action:
                  - rds:StopDBInstance
                Effect: Allow
                Resource: !Ref DB
              - Action:
                  - rds:AddTagsToResource
                  - rds:ListTagsForResource
                  - rds:RemoveTagsFromResource
                Effect: Allow
                Resource: !Ref DB
                Condition:
                  ForAllValues:StringEquals:
                    aws:TagKeys:
                      - DbStopperLastSeen
  DatabaseStopperPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !GetAtt DatabaseStopperFunction.Arn
      Principal: events.amazonaws.com
      SourceArn: !GetAtt DatabaseStopperRule.Arn
  DatabaseStopperRule:
    Type: AWS::Events::Rule
    Properties:
      EventPattern:
        source:
          - aws.rds
        detail-type:
          - "RDS DB Instance Event"
        resources:
          - !Ref DB
        detail:
          Message:
            - "DB instance is being started due to it exceeding the maximum allowed time being stopped."
            - "DB instance started"
      Targets:
        - Arn: !GetAtt DatabaseStopperFunction.Arn
          Id: DatabaseStopperLambda

It has worked for at least one person. If you have issues please report here.

kichik
  • 33,220
  • 7
  • 94
  • 114
  • 17
    That is an extremely disappointing aspect of a new "feature". To park this instance I now need to log in every 7 days and shut it down, or I end up paying money for it. What a terrible decision by AWS. Normally I love AWS, but this is a bit frustrating. Thanks for the help, though, and clarifying. – SH10151 Jan 24 '18 at 19:51
  • 2
    Or you can script this with a scheduled Lambda. – kichik Jan 24 '18 at 20:05
  • 7
    Ok, I'll check into this, kchick, thanks. Btw, why would my question get "down voted" to be "-1"? Am I being punished for asking a question??? /boggle. It is a legit question and others might have the same issue... – SH10151 Jan 28 '18 at 01:12
  • 2
    Agreed, it is a very good question, certainly useful to me! I am very disappointed by this aspect of the feature as well. @kichick, do you have experience with a Lambda script keeping the RDS instance asleep? – mitchus Jun 14 '18 at 07:42
  • 5
    @SH10151 You can take a snapshot and delete the DB and use the AMI when you launch a new instance. –  Sep 03 '18 at 12:17
  • 1
    Ok what? there shouldn't be something automatically starting a service that can charge me money. This should be an opt in feature not a default that cannot be changed. They could at least change "Stop instance" to "temporarily pause instance." That way it would be clear that's the expected result. I'm requesting a refund and I sure hope I can get it. This seems like a shady practice to me. – Felipe Centeno May 04 '22 at 21:33