1 | # Amazon DynamoDB Construct Library
|
2 |
|
3 |
|
4 | ---
|
5 |
|
6 | ![End-of-Support](https://img.shields.io/badge/End--of--Support-critical.svg?style=for-the-badge)
|
7 |
|
8 | > AWS CDK v1 has reached End-of-Support on 2023-06-01.
|
9 | > This package is no longer being updated, and users should migrate to AWS CDK v2.
|
10 | >
|
11 | > For more information on how to migrate, see the [_Migrating to AWS CDK v2_ guide][doc].
|
12 | >
|
13 | > [doc]: https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html
|
14 |
|
15 | ---
|
16 |
|
17 |
|
18 |
|
19 | Here is a minimal deployable DynamoDB table definition:
|
20 |
|
21 | ```ts
|
22 | const table = new dynamodb.Table(this, 'Table', {
|
23 | partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
|
24 | });
|
25 | ```
|
26 |
|
27 | ## Importing existing tables
|
28 |
|
29 | To import an existing table into your CDK application, use the `Table.fromTableName`, `Table.fromTableArn` or `Table.fromTableAttributes`
|
30 | factory method. This method accepts table name or table ARN which describes the properties of an already
|
31 | existing table:
|
32 |
|
33 | ```ts
|
34 | declare const user: iam.User;
|
35 | const table = dynamodb.Table.fromTableArn(this, 'ImportedTable', 'arn:aws:dynamodb:us-east-1:111111111:table/my-table');
|
36 | // now you can just call methods on the table
|
37 | table.grantReadWriteData(user);
|
38 | ```
|
39 |
|
40 | If you intend to use the `tableStreamArn` (including indirectly, for example by creating an
|
41 | `@aws-cdk/aws-lambda-event-source.DynamoEventSource` on the imported table), you *must* use the
|
42 | `Table.fromTableAttributes` method and the `tableStreamArn` property *must* be populated.
|
43 |
|
44 | ## Keys
|
45 |
|
46 | When a table is defined, you must define it's schema using the `partitionKey`
|
47 | (required) and `sortKey` (optional) properties.
|
48 |
|
49 | ## Billing Mode
|
50 |
|
51 | DynamoDB supports two billing modes:
|
52 |
|
53 | * PROVISIONED - the default mode where the table and global secondary indexes have configured read and write capacity.
|
54 | * PAY_PER_REQUEST - on-demand pricing and scaling. You only pay for what you use and there is no read and write capacity for the table or its global secondary indexes.
|
55 |
|
56 | ```ts
|
57 | const table = new dynamodb.Table(this, 'Table', {
|
58 | partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
|
59 | billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
|
60 | });
|
61 | ```
|
62 |
|
63 | Further reading:
|
64 | https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.
|
65 |
|
66 | ## Table Class
|
67 |
|
68 | DynamoDB supports two table classes:
|
69 |
|
70 | * STANDARD - the default mode, and is recommended for the vast majority of workloads.
|
71 | * STANDARD_INFREQUENT_ACCESS - optimized for tables where storage is the dominant cost.
|
72 |
|
73 | ```ts
|
74 | const table = new dynamodb.Table(this, 'Table', {
|
75 | partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
|
76 | tableClass: dynamodb.TableClass.STANDARD_INFREQUENT_ACCESS,
|
77 | });
|
78 | ```
|
79 |
|
80 | Further reading:
|
81 | https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.TableClasses.html
|
82 |
|
83 | ## Configure AutoScaling for your table
|
84 |
|
85 | You can have DynamoDB automatically raise and lower the read and write capacities
|
86 | of your table by setting up autoscaling. You can use this to either keep your
|
87 | tables at a desired utilization level, or by scaling up and down at pre-configured
|
88 | times of the day:
|
89 |
|
90 | Auto-scaling is only relevant for tables with the billing mode, PROVISIONED.
|
91 |
|
92 | [Example of configuring autoscaling](test/integ.autoscaling.lit.ts)
|
93 |
|
94 | Further reading:
|
95 | https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AutoScaling.html
|
96 | https://aws.amazon.com/blogs/database/how-to-use-aws-cloudformation-to-configure-auto-scaling-for-amazon-dynamodb-tables-and-indexes/
|
97 |
|
98 | ## Amazon DynamoDB Global Tables
|
99 |
|
100 | You can create DynamoDB Global Tables by setting the `replicationRegions` property on a `Table`:
|
101 |
|
102 | ```ts
|
103 | const globalTable = new dynamodb.Table(this, 'Table', {
|
104 | partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
|
105 | replicationRegions: ['us-east-1', 'us-east-2', 'us-west-2'],
|
106 | });
|
107 | ```
|
108 |
|
109 | When doing so, a CloudFormation Custom Resource will be added to the stack in order to create the replica tables in the
|
110 | selected regions.
|
111 |
|
112 | The default billing mode for Global Tables is `PAY_PER_REQUEST`.
|
113 | If you want to use `PROVISIONED`,
|
114 | you have to make sure write auto-scaling is enabled for that Table:
|
115 |
|
116 | ```ts
|
117 | const globalTable = new dynamodb.Table(this, 'Table', {
|
118 | partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
|
119 | replicationRegions: ['us-east-1', 'us-east-2', 'us-west-2'],
|
120 | billingMode: dynamodb.BillingMode.PROVISIONED,
|
121 | });
|
122 |
|
123 | globalTable.autoScaleWriteCapacity({
|
124 | minCapacity: 1,
|
125 | maxCapacity: 10,
|
126 | }).scaleOnUtilization({ targetUtilizationPercent: 75 });
|
127 | ```
|
128 |
|
129 | When adding a replica region for a large table, you might want to increase the
|
130 | timeout for the replication operation:
|
131 |
|
132 | ```ts
|
133 | const globalTable = new dynamodb.Table(this, 'Table', {
|
134 | partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
|
135 | replicationRegions: ['us-east-1', 'us-east-2', 'us-west-2'],
|
136 | replicationTimeout: Duration.hours(2), // defaults to Duration.minutes(30)
|
137 | });
|
138 | ```
|
139 |
|
140 | ## Encryption
|
141 |
|
142 | All user data stored in Amazon DynamoDB is fully encrypted at rest. When creating a new table, you can choose to encrypt using the following customer master keys (CMK) to encrypt your table:
|
143 |
|
144 | * AWS owned CMK - By default, all tables are encrypted under an AWS owned customer master key (CMK) in the DynamoDB service account (no additional charges apply).
|
145 | * AWS managed CMK - AWS KMS keys (one per region) are created in your account, managed, and used on your behalf by AWS DynamoDB (AWS KMS charges apply).
|
146 | * Customer managed CMK - You have full control over the KMS key used to encrypt the DynamoDB Table (AWS KMS charges apply).
|
147 |
|
148 | Creating a Table encrypted with a customer managed CMK:
|
149 |
|
150 | ```ts
|
151 | const table = new dynamodb.Table(this, 'MyTable', {
|
152 | partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
|
153 | encryption: dynamodb.TableEncryption.CUSTOMER_MANAGED,
|
154 | });
|
155 |
|
156 | // You can access the CMK that was added to the stack on your behalf by the Table construct via:
|
157 | const tableEncryptionKey = table.encryptionKey;
|
158 | ```
|
159 |
|
160 | You can also supply your own key:
|
161 |
|
162 | ```ts
|
163 | import * as kms from '@aws-cdk/aws-kms';
|
164 |
|
165 | const encryptionKey = new kms.Key(this, 'Key', {
|
166 | enableKeyRotation: true,
|
167 | });
|
168 | const table = new dynamodb.Table(this, 'MyTable', {
|
169 | partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
|
170 | encryption: dynamodb.TableEncryption.CUSTOMER_MANAGED,
|
171 | encryptionKey, // This will be exposed as table.encryptionKey
|
172 | });
|
173 | ```
|
174 |
|
175 | In order to use the AWS managed CMK instead, change the code to:
|
176 |
|
177 | ```ts
|
178 | const table = new dynamodb.Table(this, 'MyTable', {
|
179 | partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
|
180 | encryption: dynamodb.TableEncryption.AWS_MANAGED,
|
181 | });
|
182 |
|
183 | // In this case, the CMK _cannot_ be accessed through table.encryptionKey.
|
184 | ```
|
185 |
|
186 | ## Get schema of table or secondary indexes
|
187 |
|
188 | To get the partition key and sort key of the table or indexes you have configured:
|
189 |
|
190 | ```ts
|
191 | declare const table: dynamodb.Table;
|
192 | const schema = table.schema();
|
193 | const partitionKey = schema.partitionKey;
|
194 | const sortKey = schema.sortKey;
|
195 |
|
196 | // In case you want to get schema details for any secondary index
|
197 | // const { partitionKey, sortKey } = table.schema(INDEX_NAME);
|
198 | ```
|
199 |
|
200 | ## Kinesis Stream
|
201 |
|
202 | A Kinesis Data Stream can be configured on the DynamoDB table to capture item-level changes.
|
203 |
|
204 | ```ts
|
205 | import * as kinesis from '@aws-cdk/aws-kinesis';
|
206 |
|
207 | const stream = new kinesis.Stream(this, 'Stream');
|
208 |
|
209 | const table = new dynamodb.Table(this, 'Table', {
|
210 | partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
|
211 | kinesisStream: stream,
|
212 | });
|
213 | ```
|