Skip to content
Quest 03Beginner14 min

A Table with Keys

The Pokédex needs a table: one item per Pokémon form, fast lookups by number, and a way to list Pokémon by type. If you took Learn DynamoDB, this is the same table, described as code; if not, the keys and index are explained as we go.

What you'll learn

  • partitionKey and sortKey are attribute objects with a name and a type: STRING, NUMBER or BINARY.
  • The default billing mode is provisioned, 5 read and 5 write capacity units. Choose PAY_PER_REQUEST deliberately.
  • Point-in-time recovery is off by default. In current CDK it is set with pointInTimeRecoverySpecification; the older pointInTimeRecovery boolean is deprecated.

Section 01

Keys and billing

The key schema can't be changed after the table exists, so the first decision is the most important. The Pokédex uses the Pokédex number as the partition key and a form id as the sort key, so one number can hold several forms (a regional variant, a mega evolution). The number is a Number: as a string, “10” would sort before “9”.

billingMode chooses between on-demand and provisioned capacity. On-demand (PAY_PER_REQUEST) is the simplest choice for a new, unpredictable workload.

The Pokédex table
import * as dynamodb from "aws-cdk-lib/aws-dynamodb";

const table = new dynamodb.Table(this, "PokedexTable", {
  partitionKey: { name: "pokedexNumber", type: dynamodb.AttributeType.NUMBER },
  sortKey: { name: "formId", type: dynamodb.AttributeType.STRING },
  billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
  pointInTimeRecoverySpecification: { pointInTimeRecoveryEnabled: true },
});

Section 02

A global secondary index

To list Pokémon by type you add a global secondary index (GSI) with primaryType as its partition key. Call a method on the table, rather than passing a prop: that is the L2 style for things you can add later.

Add the byType index
table.addGlobalSecondaryIndex({
  indexName: "byType",
  partitionKey: { name: "primaryType", type: dynamodb.AttributeType.STRING },
});

Section 03

Read the template

Open the output of the exercise: the table becomes AWS::DynamoDB::Table with KeySchema, AttributeDefinitions (only keys and index keys are listed there, because DynamoDB is schemaless for everything else), BillingMode and GlobalSecondaryIndexes. With on-demand billing, CDK also omits provisioned throughput from the index.

Like buckets, tables default to RETAIN. That is the right default for data you care about. Production keeps it; Quest 9 shows how to choose per environment.

Practice

Your turn

Describe the Pokédex table. Its partition key is the Pokédex number (a Number) and its sort key is the form (a String) — the starter has the wrong key type and no sort key. Bill on demand, turn on point-in-time recovery, and add a global secondary index named byType on the primaryType String attribute.

pokedexNumber NUMBER + formId STRING keys, PAY_PER_REQUEST, point-in-time recovery, and a byType index.
Tab inserts two spaces. Press Escape, then Tab, to leave the editor. Control or Command plus Enter runs the code.
Simulated — no AWS calls

The simulator runs the constructs this course teaches, plus simple loops and helper methods. Other CDK code may not be recognised.

Check

Check your understanding

Quick Quiz · one question, as many tries as you need.

You deploy a table, then realise the partition key should have been a Number, not a String. What does CDK do if you change the attribute type in code?

Choose one answer.