Defining DynamoDB Tables in CloudFormation
This tutorial 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 tutorial we’re going to look at how you define DynamoDB tables with CloudFormation. We’ll look first at basic tables with either single hash keys or combined hash and range keys. We’ll then look at how you define a table that includes a global secondary index.
Defining Tables with a Single Hash Key
The first example we’ll look at shows more or less the minimum number of properties possible for a DynamoDB table. Here’s the DealerTable resource, from the services.yaml template in the SAM version of the code:
Let’s start with the BillingMode property, shown above on line 70. Possible values for this property are PROVISIONED and PAY_PER_REQUEST. By using the latter value, this example specifies on-demand pricing and capacity for the table. When this property is set to the PROVISIONED option, the table resource must also specify the two required read and write capacity unit properties within a ProvisionedThroughput element.
The other two elements to note are the AttributeDefinitions and the KeySchema. The former defines the name and data type for the table attributes that will be used as keys. The latter references the attribute names that are defined in these definitions, and specifies a KeyType property to indicate whether an attribute is a hash or a range key.
There are a couple of additional elements not shown here that we’ll cover in the labs, including the DeletionProtectionEnabled property and the PointInTimeRecoverySpecification. More on these later.
Defining Tables with Hash & Range Keys
The TimeslotTable resource, shown below, is very similar to the DealerTable shown above. The difference is that the DealerTable only has a hash key, while this table also has a range key. As a result, there’s an extra attribute in the AttributeDefinitions element, on lines 81-82, and a corresponding element in the KeySchema element for the range key, on lines 87-88:
Defining Tables with Global Secondary Indexes
The RegistrationTable, shown below, is similar to the TimeslotTable in that it has both a hash key and range key. But in addition, this table resource also defines a GlobalSecondaryIndexes element:
Under the GlobalSecondaryIndexes element, on line 137, you can see an index name that doesn’t use the !Sub function to interpolate the service and environment parameter values, unlike most resource names. That’s because this index is owned by the table and isn’t visible outside of it. Put another way, you can create multiple tables in the same account and region with this same index name, and there won’t be any name collisions.
The KeySchema element, starting on line 138, maps the attributes from the source table and specifies their key types. Note that any attributes defined for the index must also be defined for the table. The Projection element, on lines 143-144, is where you can specify which additional attributes in the table will be populated in the index. In this case, we’re projecting all the attributes. As you’ll see in the code tutorials, this makes it possible to read values from indexes using the same mapped data classes as for the source tables.