Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dynamodb): add warm-throughput to L2 #32128

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions packages/aws-cdk-lib/aws-dynamodb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,26 @@ const globalTable = new dynamodb.TableV2(this, 'Table', {
Further reading:
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html

## Warm Throughput
Warm throughput refers to the number of read and write operations your DynamoDB table can instantaneously support.

This optional configuration allows you to pre-warm your table or index to handle anticipated throughput, ensuring optimal performance under expected load.

The Warm Throughput configuration settings are automatically replicated across all Global Table replicas.

```ts
const table = new dynamodb.TableV2(this, 'Table', {
partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
warmThroughput: {
readUnitsPerSecond: 15000,
writeUnitsPerSecond: 20000,
},
});
```
Further reading:
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/warm-throughput.html


## Encryption

All user data stored in a DynamoDB table is fully encrypted at rest. When creating an instance of the `TableV2` construct, you can select the following table encryption options:
Expand Down
19 changes: 19 additions & 0 deletions packages/aws-cdk-lib/aws-dynamodb/TABLE_V1_API.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,25 @@ const table = new dynamodb.Table(this, 'Table', {
Further reading:
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.

## Warm Throughput
Warm throughput refers to the number of read and write operations your DynamoDB table can instantaneously support.

This optional configuration allows you to pre-warm your table or index to handle anticipated throughput, ensuring optimal performance under expected load.

Note: The Warm Throughput feature is not available for Global Table replicas using `Table` construct; use the `TableV2` construct instead to enable this functionality.

```ts
const table = new dynamodb.Table(this, 'Table', {
partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
warmThroughput: {
readUnitsPerSecond: 15000,
writeUnitsPerSecond: 20000,
},
});
```
Further reading:
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/warm-throughput.html

## Table Class

DynamoDB supports two table classes:
Expand Down
16 changes: 16 additions & 0 deletions packages/aws-cdk-lib/aws-dynamodb/lib/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,22 @@ export interface Attribute {
readonly type: AttributeType;
}

/**
* Reference to WarmThroughput for a DynamoDB table
*/
export interface WarmThroughput {
/**
* Configures the number of read units per second a table will be able to handle instantly
* @default - no readUnitsPerSecond configured
*/
readonly readUnitsPerSecond?: number;
/**
* Configures the number of write units per second a table will be able to handle instantly
* @default - no writeUnitsPerSecond configured
*/
readonly writeUnitsPerSecond?: number;
}

/**
* Data types for attributes within a table
*
Expand Down
19 changes: 19 additions & 0 deletions packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
SecondaryIndexProps,
StreamViewType,
TableClass,
WarmThroughput,
} from './shared';
import { ITableV2, TableBaseV2 } from './table-v2-base';
import { PolicyDocument } from '../../aws-iam';
Expand Down Expand Up @@ -118,6 +119,13 @@ export interface GlobalSecondaryIndexPropsV2 extends SecondaryIndexProps {
* @default - inherited from the primary table.
*/
readonly maxWriteRequestUnits?: number;

/**
* The warm throughput configuration for the global secondary index.
*
* @default - no warm throughput is configured
*/
readonly warmThroughput?: WarmThroughput;
}

/**
Expand Down Expand Up @@ -298,6 +306,13 @@ export interface TablePropsV2 extends TableOptionsV2 {
* @default TableEncryptionV2.dynamoOwnedKey()
*/
readonly encryption?: TableEncryptionV2;

/**
* The warm throughput configuration for the table.
*
* @default - no warm throughput is configured
*/
readonly warmThroughput?: WarmThroughput;
}

/**
Expand Down Expand Up @@ -576,6 +591,7 @@ export class TableV2 extends TableBaseV2 {
timeToLiveSpecification: props.timeToLiveAttribute
? { attributeName: props.timeToLiveAttribute, enabled: true }
: undefined,
warmThroughput: props.warmThroughput ?? undefined,
});
resource.applyRemovalPolicy(props.removalPolicy);

Expand Down Expand Up @@ -741,6 +757,8 @@ export class TableV2 extends TableBaseV2 {

props.maxReadRequestUnits && this.globalSecondaryIndexMaxReadUnits.set(props.indexName, props.maxReadRequestUnits);

const warmThroughput = props.warmThroughput ?? undefined;

const writeOnDemandThroughputSettings: CfnGlobalTable.WriteOnDemandThroughputSettingsProperty | undefined = props.maxWriteRequestUnits
? { maxWriteRequestUnits: props.maxWriteRequestUnits }
: undefined;
Expand All @@ -751,6 +769,7 @@ export class TableV2 extends TableBaseV2 {
projection,
writeProvisionedThroughputSettings,
writeOnDemandThroughputSettings,
warmThroughput,
};
}

Expand Down
19 changes: 18 additions & 1 deletion packages/aws-cdk-lib/aws-dynamodb/lib/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ScalableTableAttribute } from './scalable-table-attribute';
import {
Operation, OperationsMetricOptions, SystemErrorsForOperationsMetricOptions,
Attribute, BillingMode, ProjectionType, ITable, SecondaryIndexProps, TableClass,
LocalSecondaryIndexProps, TableEncryption, StreamViewType,
LocalSecondaryIndexProps, TableEncryption, StreamViewType, WarmThroughput,
} from './shared';
import * as appscaling from '../../aws-applicationautoscaling';
import * as cloudwatch from '../../aws-cloudwatch';
Expand Down Expand Up @@ -259,6 +259,14 @@ export interface TableOptions extends SchemaOptions {
*/
readonly billingMode?: BillingMode;

/**
* Specify values to pre-warm you DynamoDB Table
* Warm Throughput feature is not available for Global Table replicas using the `Table` construct. To enable Warm Throughput, use the `TableV2` construct instead.
* @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-warmthroughput
* @default - warm throughput is not configured
*/
readonly warmThroughput?: WarmThroughput;

/**
* Whether point-in-time recovery is enabled.
* @default - point-in-time recovery is disabled
Expand Down Expand Up @@ -457,6 +465,13 @@ export interface GlobalSecondaryIndexProps extends SecondaryIndexProps, SchemaOp
*/
readonly maxWriteRequestUnits?: number;

/**
* The warm throughput configuration for the global secondary index.
*
* @default - no warm throughput is configured
*/
readonly warmThroughput?: WarmThroughput;

/**
* Whether CloudWatch contributor insights is enabled for the specified global secondary index.
*
Expand Down Expand Up @@ -1187,6 +1202,7 @@ export class Table extends TableBase {
resourcePolicy: props.resourcePolicy
? { policyDocument: props.resourcePolicy }
: undefined,
warmThroughput: props.warmThroughput?? undefined,
});
this.table.applyRemovalPolicy(props.removalPolicy);

Expand Down Expand Up @@ -1249,6 +1265,7 @@ export class Table extends TableBase {
maxWriteRequestUnits: props.maxWriteRequestUnits || undefined,
},
} : undefined),
warmThroughput: props.warmThroughput ?? undefined,
});

this.secondaryIndexSchemas.set(props.indexName, {
Expand Down
141 changes: 141 additions & 0 deletions packages/aws-cdk-lib/aws-dynamodb/test/dynamodb.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3642,3 +3642,144 @@ test('Resource policy test', () => {
},
});
});

test('Warm Throughput test on-demand', () => {
// GIVEN
const app = new App();
const stack = new Stack(app, 'Stack');

// WHEN
const table = new Table(stack, 'Table', {
partitionKey: { name: 'id', type: AttributeType.STRING },
warmThroughput: {
readUnitsPerSecond: 13000,
writeUnitsPerSecond: 5000,
},
});

table.addGlobalSecondaryIndex({
indexName: 'my-index-1',
partitionKey: { name: 'gsi1pk', type: AttributeType.STRING },
warmThroughput: {
readUnitsPerSecond: 15000,
writeUnitsPerSecond: 6000,
},
});

table.addGlobalSecondaryIndex({
indexName: 'my-index-2',
partitionKey: { name: 'gsi2pk', type: AttributeType.STRING },
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::DynamoDB::Table', {
KeySchema: [
{ AttributeName: 'id', KeyType: 'HASH' },
],
AttributeDefinitions: [
{ AttributeName: 'id', AttributeType: 'S' },
{ AttributeName: 'gsi1pk', AttributeType: 'S' },
{ AttributeName: 'gsi2pk', AttributeType: 'S' },
],
WarmThroughput: {
ReadUnitsPerSecond: 13000,
WriteUnitsPerSecond: 5000,
},
GlobalSecondaryIndexes: [
{
IndexName: 'my-index-1',
KeySchema: [
{ AttributeName: 'gsi1pk', KeyType: 'HASH' },
],
Projection: { ProjectionType: 'ALL' },
WarmThroughput: {
ReadUnitsPerSecond: 15000,
WriteUnitsPerSecond: 6000,
},
},
{
IndexName: 'my-index-2',
KeySchema: [
{ AttributeName: 'gsi2pk', KeyType: 'HASH' },
],
Projection: { ProjectionType: 'ALL' },
},
],
});

});

test('Warm Throughput test provisioned', () => {
// GIVEN
const app = new App();
const stack = new Stack(app, 'Stack');

// WHEN
const table = new Table(stack, 'Table', {
partitionKey: { name: 'id', type: AttributeType.STRING },
readCapacity: 5,
writeCapacity: 6,
warmThroughput: {
readUnitsPerSecond: 2000,
writeUnitsPerSecond: 1000,
},
});

table.addGlobalSecondaryIndex({
indexName: 'my-index-1',
partitionKey: { name: 'gsi1pk', type: AttributeType.STRING },
readCapacity: 7,
writeCapacity: 8,
warmThroughput: {
readUnitsPerSecond: 3000,
writeUnitsPerSecond: 4000,
},
});

table.addGlobalSecondaryIndex({
indexName: 'my-index-2',
partitionKey: { name: 'gsi2pk', type: AttributeType.STRING },
readCapacity: 9,
writeCapacity: 10,
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::DynamoDB::Table', {
KeySchema: [
{ AttributeName: 'id', KeyType: 'HASH' },
],
AttributeDefinitions: [
{ AttributeName: 'id', AttributeType: 'S' },
{ AttributeName: 'gsi1pk', AttributeType: 'S' },
{ AttributeName: 'gsi2pk', AttributeType: 'S' },
],
WarmThroughput: {
ReadUnitsPerSecond: 2000,
WriteUnitsPerSecond: 1000,
},
ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 6 },
GlobalSecondaryIndexes: [
{
IndexName: 'my-index-1',
KeySchema: [
{ AttributeName: 'gsi1pk', KeyType: 'HASH' },
],
Projection: { ProjectionType: 'ALL' },
WarmThroughput: {
ReadUnitsPerSecond: 3000,
WriteUnitsPerSecond: 4000,
},
ProvisionedThroughput: { ReadCapacityUnits: 7, WriteCapacityUnits: 8 },
},
{
IndexName: 'my-index-2',
KeySchema: [
{ AttributeName: 'gsi2pk', KeyType: 'HASH' },
],
Projection: { ProjectionType: 'ALL' },
ProvisionedThroughput: { ReadCapacityUnits: 9, WriteCapacityUnits: 10 },
},
],
});

});
Loading
Loading