An independent guide to building modern software for serverless and native cloud

Protecting DynamoDB Data

This lab references the code in the aws-connectedcar-dotnet-serverless repository. If you're new to this course, see the introduction for information about setting up your workstation and getting the sample code.

In this final lab for the section, we’re going to look at two ways you can add extra layers of protection for the data in your DynamoDB tables. First, we’ll look at the point-in-time-recovery feature, which provides continuous incremental data backups. Then we’ll test the delete protection feature for tables.

Protecting Data with Point-in-Time Recovery

The point-in-time-recovery (PITR) feature for DynamoDB tables is a way to protect your data from loss due to things like errant application logic or fumbled command-line updates. You wouldn’t normally have production data in DynamoDB without this feature turned on, so let’s see how it works.

Step 1: Enable point-in-time-recovery in the services.yaml template

Activating this feature requires the addition of only two lines per table CloudFormation templates:

PointInTimeRecoverySpecification:
  PointInTimeRecoveryEnabled: true

Add these two lines of code to the DealerTable resource in the services.yaml template, as shown below:

Step 2: Deploy the services.yaml template update

Next, run the deploy.zsh script to update the CloudFormation stack. As always, once the stack outputs are written in the VS Code terminal, the update is complete:

You can verify the update to the dealer table in the console. Navigate to the DynamoDB service, select the “Tables” menu option on the left, then the “ConnectedCar_Dealer_Table_Dev” table, and finally, select the “Backups” tab. You should see the “On” status on the “Point-in-time Recovery” panel, as shown below, along with timestamps for the earliest and latest restore points:

Step 3: Wait for ten minutes

Set a timer and wait for ten minutes.

Step 4: Delete a sample dealer item in the console

Navigate to the Explore items page in the console, select the “ConnectedCar_Dealer_Table_Dev” table, and pick a random item in the list. Copy and paste the dealerId for this item to a text editor, and then select the item and delete it. You can use the query panel at the top of the page, as we did in the earlier lab, and query for this item by the dealerId. As shown below, it should not be found:

Step 5: Run the restore-table.zsh script in the terminal

You’re now ready to restore the table to a point-in-time before you deleted the item, from ten minutes ago. Open the “aws-connectedcar-common” repository in VS Code and open the restore-table.zsh script that’s in the “/scripts/dynamodb/zsh” folder:

This script generates a timestamp for ten minutes prior, and then calls the “dynamodb restore-table-to-point-in-time” command, specifying source and target tables along with the restore date/time.

Run this script, after which you should see JSON output something like this:

Switch back to the console and select the “Tables” menu, where you should see the new target table in the process of being restored, as shown below:

Step 6: Query for the deleted item in the restored table

Lastly, while still in the console, select the restored table on the “Explore items” page, open the query panel and paste in the dealerId for the item previously deleted. When you run the query you should get a result for this item, demonstrating that the deleted data has been restored:

Protecting Data with Delete Protection

The point-in-time recovery feature provides your table data with some protection from mistaken data updates. But, you also need to protect table data from those console or command line fumbles that delete tables entirely. With point-in-time-recovery activated, AWS will automatically create a restored copy of a table from the most recent recovery point after deletion. However, it saves a lot of recovery work if you use use the delete protection feature to prevent the deletion in the first place.

Step 7: Enable delete protection in the services.yaml template

You enable delete protection for a table by adding this line of code to a table resource:

DeletionProtectionEnabled: true

Add this code to the DealerTable resource in the services.yaml template, as shown below:

Step 8: Deploy the services.yaml template update

Run the deploy.zsh script to again deploy the updated template. Once deployed, you can confirm that the feature is activated by looking at the “Additional info” panel for the table, on the “Overview” tab as shown below on the lower right:

Step 9: Attempt to delete the deployed stack in the console

Next, delete the deployed stack in CloudFormation in the console, as done previously, by selecting the parent stack and clicking the “Delete” button. The deletion will proceed normally until it gets to the service stack, at which point it should fail, as shown below:

Click on the service stack and select the “Events” tab. You should see the message for the error that triggered the failed deletion:

Now go back to the main stacks page and perform the delete on the parent stack again. This time you should get a dialog box like this:

CloudFormation is now giving you the opportunity to delete the stack, but also retain resources that are failing to delete, which in this case is the child ServiceStack. Select the checkbox and click the orange “Delete” button to proceed. The parent stack will now be deleted, but the service stack will remain. Now you can attempt to delete this stack, at which point you will again see this dialog box, but this time offering to retain the DealerTable resource:

Once more, select the DealerTable and proceed. The stack should now be entirely deleted, as shown below:

Step 10: Verify that the dealer table remains

Lastly, go to the Tables page for the DynamoDB service and verify that the dealer table still exists:

Having stepped through the stack deletion process with this feature enabled, here are some observations. First, note that the CloudFormation delete operation failed without rolling back to its prior state. CloudFormation create- and update-stack operations are transactional, but delete-stack operations appear not to be. Second, the delete protection feature doesn’t make it impossible to delete a table, but you get warnings as you move through the stack and resource deletion steps shown above. So you still have the power to delete protected tables, but you get warnings so that it can’t happen by accident.

Deleting the Remaining Tables

At this point there are still two leftover tables that you need to delete. To delete the dealer table, you’ll first have to turn off the delete protection.

Step 11: Turn off delete protection for the dealer table from the console

Navigate to the DynamoDB service in the console and select the “Tables” menu option. Select the “ConnectedCar_Dealer_Table_Dev” table and click on the “Additional settings” tab on the far right. Scroll down to the “Deletion protection” panel, where you should see a “Turn off” button. When you click this button, not surprisingly you get a warning dialog, as shown below:

Click the orange “Confirm” button to turn off delete protection.

Step 12: Delete the two remaining tables from the console

Navigate back to the main “Tables” page, where you should see the two remaining tables listed, both without delete protection, as shown below:

Select both tables, and click the Delete button. You’ll get one last warning dialog, shown below, where you can opt to delete all CloudWatch alarms, and skip creating on-demand backups prior to the deletion.

Type the “confirm” input and proceed. After a few seconds for the deletion to complete, you should see an empty list of tables:

Cleaning up the Repository

As a final clean-up step, in VS Code discard the changes made in this lab to the services.yaml template. This will make it easier to deploy and tear down the solution in the labs for the next section.