@composurecdk/dynamodb 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +186 -0
  2. package/dist/commonjs/defaults.d.ts +25 -0
  3. package/dist/commonjs/defaults.d.ts.map +1 -0
  4. package/dist/commonjs/defaults.js +138 -0
  5. package/dist/commonjs/defaults.js.map +1 -0
  6. package/dist/commonjs/index.d.ts +6 -0
  7. package/dist/commonjs/index.d.ts.map +1 -0
  8. package/dist/commonjs/index.js +13 -0
  9. package/dist/commonjs/index.js.map +1 -0
  10. package/dist/commonjs/package.json +3 -0
  11. package/dist/commonjs/table-alarm-config.d.ts +58 -0
  12. package/dist/commonjs/table-alarm-config.d.ts.map +1 -0
  13. package/dist/commonjs/table-alarm-config.js +3 -0
  14. package/dist/commonjs/table-alarm-config.js.map +1 -0
  15. package/dist/commonjs/table-alarm-defaults.d.ts +21 -0
  16. package/dist/commonjs/table-alarm-defaults.d.ts.map +1 -0
  17. package/dist/commonjs/table-alarm-defaults.js +51 -0
  18. package/dist/commonjs/table-alarm-defaults.js.map +1 -0
  19. package/dist/commonjs/table-alarms.d.ts +26 -0
  20. package/dist/commonjs/table-alarms.d.ts.map +1 -0
  21. package/dist/commonjs/table-alarms.js +129 -0
  22. package/dist/commonjs/table-alarms.js.map +1 -0
  23. package/dist/commonjs/table-builder.d.ts +123 -0
  24. package/dist/commonjs/table-builder.d.ts.map +1 -0
  25. package/dist/commonjs/table-builder.js +86 -0
  26. package/dist/commonjs/table-builder.js.map +1 -0
  27. package/dist/commonjs/table-v2-builder.d.ts +129 -0
  28. package/dist/commonjs/table-v2-builder.d.ts.map +1 -0
  29. package/dist/commonjs/table-v2-builder.js +71 -0
  30. package/dist/commonjs/table-v2-builder.js.map +1 -0
  31. package/dist/esm/defaults.d.ts +25 -0
  32. package/dist/esm/defaults.d.ts.map +1 -0
  33. package/dist/esm/defaults.js +135 -0
  34. package/dist/esm/defaults.js.map +1 -0
  35. package/dist/esm/index.d.ts +6 -0
  36. package/dist/esm/index.d.ts.map +1 -0
  37. package/dist/esm/index.js +5 -0
  38. package/dist/esm/index.js.map +1 -0
  39. package/dist/esm/package.json +3 -0
  40. package/dist/esm/table-alarm-config.d.ts +58 -0
  41. package/dist/esm/table-alarm-config.d.ts.map +1 -0
  42. package/dist/esm/table-alarm-config.js +2 -0
  43. package/dist/esm/table-alarm-config.js.map +1 -0
  44. package/dist/esm/table-alarm-defaults.d.ts +21 -0
  45. package/dist/esm/table-alarm-defaults.d.ts.map +1 -0
  46. package/dist/esm/table-alarm-defaults.js +48 -0
  47. package/dist/esm/table-alarm-defaults.js.map +1 -0
  48. package/dist/esm/table-alarms.d.ts +26 -0
  49. package/dist/esm/table-alarms.d.ts.map +1 -0
  50. package/dist/esm/table-alarms.js +125 -0
  51. package/dist/esm/table-alarms.js.map +1 -0
  52. package/dist/esm/table-builder.d.ts +123 -0
  53. package/dist/esm/table-builder.d.ts.map +1 -0
  54. package/dist/esm/table-builder.js +83 -0
  55. package/dist/esm/table-builder.js.map +1 -0
  56. package/dist/esm/table-v2-builder.d.ts +129 -0
  57. package/dist/esm/table-v2-builder.d.ts.map +1 -0
  58. package/dist/esm/table-v2-builder.js +68 -0
  59. package/dist/esm/table-v2-builder.js.map +1 -0
  60. package/package.json +80 -0
package/README.md ADDED
@@ -0,0 +1,186 @@
1
+ # @composurecdk/dynamodb
2
+
3
+ DynamoDB table builders for [ComposureCDK](../../README.md).
4
+
5
+ This package provides fluent builders for DynamoDB tables with secure, AWS-recommended defaults and built-in CloudWatch alarms. It ships **two builders**, one per CDK construct:
6
+
7
+ | Factory | CDK construct | CloudFormation resource | Use for |
8
+ | ------------------------ | ---------------------------------------------------------------------------------------------- | ---------------------------- | --------------------------------------------------------------- |
9
+ | `createTableV2Builder()` | [`TableV2`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb.TableV2.html) | `AWS::DynamoDB::GlobalTable` | **New tables (recommended).** |
10
+ | `createTableBuilder()` | [`Table`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb.Table.html) | `AWS::DynamoDB::Table` | `importSource` (S3 bulk import) and parity with classic tables. |
11
+
12
+ Both share the same well-architected defaults intent, the same recommended alarms, and the same `ref()`-able result shape — they differ only in the underlying CDK prop surface.
13
+
14
+ ### Which builder should I use?
15
+
16
+ For **new tables, prefer `createTableV2Builder()`**. A single-region `TableV2` bills the same as a classic table, but it future-proofs the one irreversible part of the decision: you can add cross-region replicas later without replacing the table. `ITableV2 extends ITable`, so a built `TableV2` works everywhere an `ITable` is expected (IAM grants, `DynamoEventSource`) — composition wiring is identical for both builders.
17
+
18
+ Reach for the classic `createTableBuilder()` when you need an `importSource` (S3 bulk import is V1-only, with no `TableV2` equivalent) or parity with existing classic tables.
19
+
20
+ > ⚠️ **`Table` and `TableV2` are different CloudFormation resources** (`AWS::DynamoDB::Table` vs. `AWS::DynamoDB::GlobalTable`). CloudFormation **cannot migrate between them in place** — swapping the construct on an existing table is a resource replacement, which deletes and recreates the table. Choose deliberately up front.
21
+
22
+ ## TableV2 builder (recommended)
23
+
24
+ ```ts
25
+ import { AttributeType, StreamViewType } from "aws-cdk-lib/aws-dynamodb";
26
+ import { createTableV2Builder } from "@composurecdk/dynamodb";
27
+
28
+ const orders = createTableV2Builder()
29
+ .partitionKey({ name: "orderId", type: AttributeType.STRING })
30
+ .sortKey({ name: "createdAt", type: AttributeType.NUMBER })
31
+ .dynamoStream(StreamViewType.NEW_AND_OLD_IMAGES)
32
+ .build(stack, "Orders");
33
+ ```
34
+
35
+ Every [`TablePropsV2`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb.TablePropsV2.html) property is available as a fluent setter. Note the V2 prop shape differs from the classic one — billing is a single `.billing(Billing.onDemand())` helper, encryption is `.encryption(TableEncryptionV2.awsManagedKey())`, and the stream is `.dynamoStream(StreamViewType…)`. `partitionKey` is the one property the builder does not default — the key schema is workload-specific, so it must be set before `build()`.
36
+
37
+ ## Classic Table builder
38
+
39
+ ```ts
40
+ import { AttributeType, StreamViewType } from "aws-cdk-lib/aws-dynamodb";
41
+ import { createTableBuilder } from "@composurecdk/dynamodb";
42
+
43
+ const orders = createTableBuilder()
44
+ .partitionKey({ name: "orderId", type: AttributeType.STRING })
45
+ .sortKey({ name: "createdAt", type: AttributeType.NUMBER })
46
+ .stream(StreamViewType.NEW_AND_OLD_IMAGES)
47
+ .build(stack, "Orders");
48
+ ```
49
+
50
+ Every [`TableProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb.TableProps.html) property is available as a fluent setter, including `importSource` for [S3 bulk import](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/S3DataImport.HowItWorks.html) — the main reason to choose the classic builder.
51
+
52
+ ## Secure Defaults
53
+
54
+ Both builders apply the same well-architected intent, encoded against each construct's prop shape. Each default can be overridden via the builder's fluent API.
55
+
56
+ | Intent | TableV2 (`TABLE_V2_DEFAULTS`) | Classic (`TABLE_DEFAULTS`) | Rationale |
57
+ | ---------------------- | ----------------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
58
+ | On-demand billing | `billing: Billing.onDemand()` | `billingMode: BillingMode.PAY_PER_REQUEST` | No forecasting, scales with traffic, avoids throttling from under-provisioning. Switch to provisioned for steady, predictable workloads. |
59
+ | Encryption at rest | `encryption: TableEncryptionV2.awsManagedKey()` | `encryption: TableEncryption.AWS_MANAGED` | Encrypts with the AWS-managed `aws/dynamodb` KMS key — visible in the account and logged in CloudTrail, unlike the free AWS-owned default key. Bring-your-own KMS is opt-in. ([Security Pillar](https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/protecting-data-at-rest.html)) |
60
+ | Point-in-time recovery | `pointInTimeRecoverySpecification: { … }` | `pointInTimeRecoverySpecification: { … }` | Continuous backups — restore to any second in the preceding 35 days. ([PITR](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery.html)) |
61
+ | Deletion protection | `deletionProtection: true` | `deletionProtection: true` | Blocks table deletion (API, console, or `cdk destroy`) until explicitly disabled. Override with `.deletionProtection(false)` for ephemeral tables. |
62
+
63
+ The defaults are exported for visibility and testing:
64
+
65
+ ```ts
66
+ import { TABLE_DEFAULTS, TABLE_V2_DEFAULTS } from "@composurecdk/dynamodb";
67
+ ```
68
+
69
+ ## DynamoDB Streams
70
+
71
+ Enable a stream with `.dynamoStream(StreamViewType…)` (TableV2) or `.stream(StreamViewType…)` (classic). The build result surfaces the stream ARN so a downstream component can wire a consumer:
72
+
73
+ ```ts
74
+ const result = createTableV2Builder()
75
+ .partitionKey({ name: "pk", type: AttributeType.STRING })
76
+ .dynamoStream(StreamViewType.NEW_AND_OLD_IMAGES)
77
+ .build(stack, "Events");
78
+
79
+ result.tableStreamArn; // string — feed into a Lambda DynamoEventSource, etc.
80
+ result.table; // the table itself, which a DynamoEventSource consumes
81
+ ```
82
+
83
+ Neither construct exposes a distinct stream construct — the stream is an attribute of the table — so the result exposes `tableStreamArn` directly. It is `undefined` when no stream is configured, on both builders, so a `ref()` consumer can branch on its presence.
84
+
85
+ ## Recommended Alarms
86
+
87
+ Both builders create the same [AWS-recommended CloudWatch alarms](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#DynamoDB) by default. No alarm actions are configured — access alarms from the build result to add SNS topics or other actions.
88
+
89
+ | Alarm | Metric | Default threshold | Rationale |
90
+ | --------------------- | ------------------------------------------- | ----------------- | ---------------------------------------------------------------- |
91
+ | `systemErrors` | `SystemErrors` (Sum across core ops, 1 min) | > 0 | Server-side (HTTP 500) faults — a table availability signal. |
92
+ | `readThrottleEvents` | `ReadThrottleEvents` (Sum, 1 min) | > 0 | Read throttling — hot partition or insufficient read capacity. |
93
+ | `writeThrottleEvents` | `WriteThrottleEvents` (Sum, 1 min) | > 0 | Write throttling — hot partition or insufficient write capacity. |
94
+
95
+ The thresholds are deliberately strict — a healthy table should sit at zero. Tune them up for workloads where brief, self-correcting throttling under burst is acceptable.
96
+
97
+ `SystemErrors` is emitted per-operation, and a CloudWatch alarm on a metric-math expression can reference at most 10 metrics, so the `systemErrors` alarm sums the ten core data-plane operations (`GetItem`, `BatchGetItem`, `Query`, `Scan`, `PutItem`, `UpdateItem`, `DeleteItem`, `BatchWriteItem`, `TransactGetItems`, `TransactWriteItems`). The PartiQL statement operations and the stream `GetRecords` operation are excluded; add a custom alarm if your errors live there.
98
+
99
+ The defaults are exported as `TABLE_ALARM_DEFAULTS` for visibility and testing:
100
+
101
+ ```ts
102
+ import { TABLE_ALARM_DEFAULTS } from "@composurecdk/dynamodb";
103
+ ```
104
+
105
+ ### What is not alarmed by default
106
+
107
+ - **Account-level utilization alarms** (`AccountProvisionedReadCapacityUtilization`, `AccountProvisionedWriteCapacityUtilization`) from the AWS recommended-alarms list are account-scoped, not table-scoped, so they do not belong to a per-table builder.
108
+ - **Provisioned-capacity utilization** (consumed vs. provisioned) only applies to provisioned tables; the default billing mode here is on-demand. Add it via `addAlarm` on a provisioned table.
109
+ - **`UserErrors` / `ConditionalCheckFailedRequests`** are caller- or application-level signals (HTTP 400) and too workload-dependent for a useful generic threshold.
110
+
111
+ ### Customizing thresholds
112
+
113
+ Override individual alarm properties via `recommendedAlarms`. Unspecified fields keep their defaults.
114
+
115
+ ```ts
116
+ const table = createTableV2Builder()
117
+ .partitionKey({ name: "pk", type: AttributeType.STRING })
118
+ .recommendedAlarms({
119
+ readThrottleEvents: { threshold: 10, evaluationPeriods: 3 },
120
+ });
121
+ ```
122
+
123
+ ### Disabling alarms
124
+
125
+ ```ts
126
+ builder.recommendedAlarms(false);
127
+ // or
128
+ builder.recommendedAlarms({ enabled: false });
129
+ // or individually
130
+ builder.recommendedAlarms({ writeThrottleEvents: false });
131
+ ```
132
+
133
+ ### Custom alarms
134
+
135
+ Add custom alarms alongside the recommended ones via `addAlarm`. The callback receives an `AlarmDefinitionBuilder` typed to `ITable`, so the metric factory has access to the table's metric helpers.
136
+
137
+ ```ts
138
+ import { Duration } from "aws-cdk-lib";
139
+
140
+ const table = createTableV2Builder()
141
+ .partitionKey({ name: "pk", type: AttributeType.STRING })
142
+ .addAlarm("userErrors", (alarm) =>
143
+ alarm
144
+ .metric((table) => table.metricUserErrors({ period: Duration.minutes(5) }))
145
+ .threshold(5)
146
+ .greaterThan()
147
+ .description("Table is returning client-side (HTTP 400) errors."),
148
+ );
149
+ ```
150
+
151
+ ### Applying alarm actions
152
+
153
+ Alarms are returned in the build result as `Record<string, Alarm>`:
154
+
155
+ ```ts
156
+ const result = createTableV2Builder()
157
+ .partitionKey({ name: "pk", type: AttributeType.STRING })
158
+ .build(stack, "Orders");
159
+
160
+ const alertTopic = new Topic(stack, "AlertTopic");
161
+ for (const alarm of Object.values(result.alarms)) {
162
+ alarm.addAlarmAction(new SnsAction(alertTopic));
163
+ }
164
+ ```
165
+
166
+ For composing the alarm-actions wiring across multiple builders in a single `compose` system, see [`alarmActionsPolicy`](../cloudwatch/README.md) in `@composurecdk/cloudwatch`.
167
+
168
+ ## Composition
169
+
170
+ Both builders implement `Lifecycle`, so they slot into a `compose` system and expose a `ref()`-able stream for wiring a consumer (e.g. a Lambda `DynamoEventSource`):
171
+
172
+ ```ts
173
+ import { compose } from "@composurecdk/core";
174
+ import { createTableV2Builder } from "@composurecdk/dynamodb";
175
+ import { createFunctionBuilder } from "@composurecdk/lambda";
176
+
177
+ const system = compose(
178
+ {
179
+ orders: createTableV2Builder()
180
+ .partitionKey({ name: "pk", type: AttributeType.STRING })
181
+ .dynamoStream(StreamViewType.NEW_AND_OLD_IMAGES),
182
+ processor: createFunctionBuilder(),
183
+ },
184
+ { orders: [], processor: ["orders"] },
185
+ );
186
+ ```
@@ -0,0 +1,25 @@
1
+ import { type TableProps, type TablePropsV2 } from "aws-cdk-lib/aws-dynamodb";
2
+ /**
3
+ * Secure, AWS-recommended defaults applied to every DynamoDB table built
4
+ * with {@link createTableBuilder}. Each property can be individually
5
+ * overridden via the builder's fluent API.
6
+ *
7
+ * `partitionKey` is intentionally not defaulted — the key schema is the
8
+ * single most workload-specific decision for a table and there is no safe
9
+ * generic value. The builder requires it to be set before {@link Lifecycle.build}.
10
+ */
11
+ export declare const TABLE_DEFAULTS: Partial<TableProps>;
12
+ /**
13
+ * Secure, AWS-recommended defaults applied to every DynamoDB table built with
14
+ * {@link createTableV2Builder}. These encode the same well-architected intent
15
+ * as {@link TABLE_DEFAULTS} (on-demand billing, AWS-managed-KMS encryption,
16
+ * point-in-time recovery, deletion protection) against the `TableV2`
17
+ * (`AWS::DynamoDB::GlobalTable`) prop shape, where billing and encryption are
18
+ * single helper objects rather than flat props.
19
+ *
20
+ * As with {@link TABLE_DEFAULTS}, `partitionKey` is intentionally not defaulted
21
+ * — the key schema is the single most workload-specific decision for a table
22
+ * and there is no safe generic value.
23
+ */
24
+ export declare const TABLE_V2_DEFAULTS: Partial<TablePropsV2>;
25
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,YAAY,EAClB,MAAM,0BAA0B,CAAC;AAElC;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,EAAE,OAAO,CAAC,UAAU,CAwD9C,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,EAAE,OAAO,CAAC,YAAY,CA4DnD,CAAC"}
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TABLE_V2_DEFAULTS = exports.TABLE_DEFAULTS = void 0;
4
+ const aws_dynamodb_1 = require("aws-cdk-lib/aws-dynamodb");
5
+ /**
6
+ * Secure, AWS-recommended defaults applied to every DynamoDB table built
7
+ * with {@link createTableBuilder}. Each property can be individually
8
+ * overridden via the builder's fluent API.
9
+ *
10
+ * `partitionKey` is intentionally not defaulted — the key schema is the
11
+ * single most workload-specific decision for a table and there is no safe
12
+ * generic value. The builder requires it to be set before {@link Lifecycle.build}.
13
+ */
14
+ exports.TABLE_DEFAULTS = {
15
+ /**
16
+ * On-demand (pay-per-request) capacity. Removes the need to forecast and
17
+ * provision read/write capacity, scales instantly with traffic, and avoids
18
+ * throttling caused by under-provisioning — the safe default for variable
19
+ * or unknown workloads. Switch to {@link BillingMode.PROVISIONED} with
20
+ * `.readCapacity()` / `.writeCapacity()` for steady, predictable traffic
21
+ * where provisioned capacity is more cost-effective.
22
+ *
23
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/serverless-applications-lens/capacity.html
24
+ * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html
25
+ */
26
+ billingMode: aws_dynamodb_1.BillingMode.PAY_PER_REQUEST,
27
+ /**
28
+ * Encrypt at rest with an AWS-managed KMS key (`aws/dynamodb`) rather than
29
+ * the default AWS-owned key. The AWS-managed key is visible in the account's
30
+ * KMS console and its use is logged in CloudTrail, giving an auditable record
31
+ * of table encryption — what the Security Pillar asks for. Bring-your-own KMS
32
+ * is opt-in: set `.encryptionKey(key)` and the builder infers
33
+ * {@link TableEncryption.CUSTOMER_MANAGED}.
34
+ *
35
+ * Note: the AWS-managed key incurs KMS API request charges that the free,
36
+ * AWS-owned key does not. Override with `.encryption(TableEncryption.DEFAULT)`
37
+ * to fall back to the AWS-owned key.
38
+ *
39
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/protecting-data-at-rest.html
40
+ * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/EncryptionAtRest.html
41
+ */
42
+ encryption: aws_dynamodb_1.TableEncryption.AWS_MANAGED,
43
+ /**
44
+ * Enable point-in-time recovery (continuous backups). Lets the table be
45
+ * restored to any second within the preceding 35 days, protecting against
46
+ * accidental writes, deletes, and application-level corruption. The Reliability
47
+ * Pillar treats automated, restorable backups as table stakes for stateful
48
+ * services.
49
+ *
50
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_backing_up_data_identified_backups_data.html
51
+ * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery.html
52
+ */
53
+ pointInTimeRecoverySpecification: { pointInTimeRecoveryEnabled: true },
54
+ /**
55
+ * Enable deletion protection so the table cannot be deleted by an API call,
56
+ * console action, or `cdk destroy` until protection is explicitly turned off.
57
+ * Guards production data against accidental teardown.
58
+ *
59
+ * This is intentionally heavier than CDK's default `RemovalPolicy.RETAIN`
60
+ * (which only orphans the table from the stack): deletion protection blocks
61
+ * the delete operation itself. Override with `.deletionProtection(false)` for
62
+ * ephemeral or test tables you expect to tear down.
63
+ *
64
+ * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.Basics.html#WorkingWithTables.Basics.DeletionProtection
65
+ */
66
+ deletionProtection: true,
67
+ };
68
+ /**
69
+ * Secure, AWS-recommended defaults applied to every DynamoDB table built with
70
+ * {@link createTableV2Builder}. These encode the same well-architected intent
71
+ * as {@link TABLE_DEFAULTS} (on-demand billing, AWS-managed-KMS encryption,
72
+ * point-in-time recovery, deletion protection) against the `TableV2`
73
+ * (`AWS::DynamoDB::GlobalTable`) prop shape, where billing and encryption are
74
+ * single helper objects rather than flat props.
75
+ *
76
+ * As with {@link TABLE_DEFAULTS}, `partitionKey` is intentionally not defaulted
77
+ * — the key schema is the single most workload-specific decision for a table
78
+ * and there is no safe generic value.
79
+ */
80
+ exports.TABLE_V2_DEFAULTS = {
81
+ /**
82
+ * On-demand (pay-per-request) capacity. Removes the need to forecast and
83
+ * provision read/write capacity, scales instantly with traffic, and avoids
84
+ * throttling caused by under-provisioning — the safe default for variable or
85
+ * unknown workloads. Switch to {@link Billing.provisioned} with
86
+ * `MaxCapacity`/`Capacity.autoscaled(...)` for steady, predictable traffic
87
+ * where provisioned capacity is more cost-effective.
88
+ *
89
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/serverless-applications-lens/capacity.html
90
+ * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html
91
+ */
92
+ billing: aws_dynamodb_1.Billing.onDemand(),
93
+ /**
94
+ * Encrypt at rest with an AWS-managed KMS key (`aws/dynamodb`) rather than the
95
+ * default AWS-owned key. The AWS-managed key is visible in the account's KMS
96
+ * console and its use is logged in CloudTrail, giving an auditable record of
97
+ * table encryption — what the Security Pillar asks for. Bring-your-own KMS is
98
+ * opt-in via `.encryption(TableEncryptionV2.customerManagedKey(key))`.
99
+ *
100
+ * Note: the AWS-managed key incurs KMS API request charges that the free,
101
+ * AWS-owned key does not. Override with
102
+ * `.encryption(TableEncryptionV2.dynamoOwnedKey())` to fall back to the
103
+ * AWS-owned key.
104
+ *
105
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/security-pillar/protecting-data-at-rest.html
106
+ * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/EncryptionAtRest.html
107
+ */
108
+ encryption: aws_dynamodb_1.TableEncryptionV2.awsManagedKey(),
109
+ /**
110
+ * Enable point-in-time recovery (continuous backups). Lets the table be
111
+ * restored to any second within the preceding 35 days, protecting against
112
+ * accidental writes, deletes, and application-level corruption. The
113
+ * Reliability Pillar treats automated, restorable backups as table stakes for
114
+ * stateful services.
115
+ *
116
+ * Note: for `TableV2` (`AWS::DynamoDB::GlobalTable`) this setting is encoded
117
+ * per-replica (`Replicas[].PointInTimeRecoverySpecification`), not at the
118
+ * resource root — CDK applies it to each replica.
119
+ *
120
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_backing_up_data_identified_backups_data.html
121
+ * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/PointInTimeRecovery.html
122
+ */
123
+ pointInTimeRecoverySpecification: { pointInTimeRecoveryEnabled: true },
124
+ /**
125
+ * Enable deletion protection so the table cannot be deleted by an API call,
126
+ * console action, or `cdk destroy` until protection is explicitly turned off.
127
+ * Guards production data against accidental teardown. Override with
128
+ * `.deletionProtection(false)` for ephemeral or test tables.
129
+ *
130
+ * Note: for `TableV2` (`AWS::DynamoDB::GlobalTable`) this setting is encoded
131
+ * per-replica (`Replicas[].DeletionProtectionEnabled`), not at the resource
132
+ * root — CDK applies it to each replica.
133
+ *
134
+ * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.Basics.html#WorkingWithTables.Basics.DeletionProtection
135
+ */
136
+ deletionProtection: true,
137
+ };
138
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/defaults.ts"],"names":[],"mappings":";;;AAAA,2DAOkC;AAElC;;;;;;;;GAQG;AACU,QAAA,cAAc,GAAwB;IACjD;;;;;;;;;;OAUG;IACH,WAAW,EAAE,0BAAW,CAAC,eAAe;IAExC;;;;;;;;;;;;;;OAcG;IACH,UAAU,EAAE,8BAAe,CAAC,WAAW;IAEvC;;;;;;;;;OASG;IACH,gCAAgC,EAAE,EAAE,0BAA0B,EAAE,IAAI,EAAE;IAEtE;;;;;;;;;;;OAWG;IACH,kBAAkB,EAAE,IAAI;CACzB,CAAC;AAEF;;;;;;;;;;;GAWG;AACU,QAAA,iBAAiB,GAA0B;IACtD;;;;;;;;;;OAUG;IACH,OAAO,EAAE,sBAAO,CAAC,QAAQ,EAAE;IAE3B;;;;;;;;;;;;;;OAcG;IACH,UAAU,EAAE,gCAAiB,CAAC,aAAa,EAAE;IAE7C;;;;;;;;;;;;;OAaG;IACH,gCAAgC,EAAE,EAAE,0BAA0B,EAAE,IAAI,EAAE;IAEtE;;;;;;;;;;;OAWG;IACH,kBAAkB,EAAE,IAAI;CACzB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { createTableBuilder, type ITableBuilder, type TableBuilderProps, type TableBuilderResult, } from "./table-builder.js";
2
+ export { createTableV2Builder, type ITableV2Builder, type TableV2BuilderProps, type TableV2BuilderResult, } from "./table-v2-builder.js";
3
+ export { TABLE_DEFAULTS, TABLE_V2_DEFAULTS } from "./defaults.js";
4
+ export { type TableAlarmConfig } from "./table-alarm-config.js";
5
+ export { TABLE_ALARM_DEFAULTS } from "./table-alarm-defaults.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TABLE_ALARM_DEFAULTS = exports.TABLE_V2_DEFAULTS = exports.TABLE_DEFAULTS = exports.createTableV2Builder = exports.createTableBuilder = void 0;
4
+ var table_builder_js_1 = require("./table-builder.js");
5
+ Object.defineProperty(exports, "createTableBuilder", { enumerable: true, get: function () { return table_builder_js_1.createTableBuilder; } });
6
+ var table_v2_builder_js_1 = require("./table-v2-builder.js");
7
+ Object.defineProperty(exports, "createTableV2Builder", { enumerable: true, get: function () { return table_v2_builder_js_1.createTableV2Builder; } });
8
+ var defaults_js_1 = require("./defaults.js");
9
+ Object.defineProperty(exports, "TABLE_DEFAULTS", { enumerable: true, get: function () { return defaults_js_1.TABLE_DEFAULTS; } });
10
+ Object.defineProperty(exports, "TABLE_V2_DEFAULTS", { enumerable: true, get: function () { return defaults_js_1.TABLE_V2_DEFAULTS; } });
11
+ var table_alarm_defaults_js_1 = require("./table-alarm-defaults.js");
12
+ Object.defineProperty(exports, "TABLE_ALARM_DEFAULTS", { enumerable: true, get: function () { return table_alarm_defaults_js_1.TABLE_ALARM_DEFAULTS; } });
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,uDAK4B;AAJ1B,sHAAA,kBAAkB,OAAA;AAKpB,6DAK+B;AAJ7B,2HAAA,oBAAoB,OAAA;AAKtB,6CAAkE;AAAzD,6GAAA,cAAc,OAAA;AAAE,gHAAA,iBAAiB,OAAA;AAE1C,qEAAiE;AAAxD,+HAAA,oBAAoB,OAAA"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,58 @@
1
+ import type { AlarmConfig } from "@composurecdk/cloudwatch";
2
+ /**
3
+ * Controls which recommended alarms are created for a DynamoDB table.
4
+ * All applicable alarms are enabled by default with AWS-recommended
5
+ * thresholds. Set individual alarms to `false` to disable them, or provide
6
+ * an {@link AlarmConfig} to tune thresholds.
7
+ *
8
+ * The defaults target a table-scoped view of availability and throttling.
9
+ * Account-level recommended alarms (e.g. `AccountProvisionedReadCapacityUtilization`)
10
+ * and provisioned-capacity utilization alarms are not created here — see the
11
+ * package README for the rationale.
12
+ *
13
+ * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#DynamoDB
14
+ */
15
+ export interface TableAlarmConfig {
16
+ /**
17
+ * Master switch: set to `false` to disable all recommended alarms.
18
+ * Individual alarms can also be disabled via their own entry.
19
+ * @default true
20
+ */
21
+ enabled?: boolean;
22
+ /**
23
+ * Alarm on server-side errors (HTTP 500) returned by the table. These are
24
+ * faults on the DynamoDB side rather than the caller's, so any sustained
25
+ * occurrence is worth surfacing. Summed across all operations.
26
+ *
27
+ * Metric: `AWS/DynamoDB SystemErrors` (summed per-operation via a math
28
+ * expression), statistic Sum, period 1 minute.
29
+ * Default threshold: > 0.
30
+ *
31
+ * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#DynamoDB
32
+ */
33
+ systemErrors?: AlarmConfig | false;
34
+ /**
35
+ * Alarm when read requests are throttled. On an on-demand table sustained
36
+ * read throttling signals traffic ramping faster than DynamoDB's adaptive
37
+ * scaling can follow, or a hot partition; on a provisioned table it signals
38
+ * under-provisioned read capacity.
39
+ *
40
+ * Metric: `AWS/DynamoDB ReadThrottleEvents`, statistic Sum, period 1 minute.
41
+ * Default threshold: > 0.
42
+ *
43
+ * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/metrics-dimensions.html
44
+ */
45
+ readThrottleEvents?: AlarmConfig | false;
46
+ /**
47
+ * Alarm when write requests are throttled. As with read throttling, this
48
+ * indicates a hot partition or capacity that cannot keep up with the write
49
+ * rate.
50
+ *
51
+ * Metric: `AWS/DynamoDB WriteThrottleEvents`, statistic Sum, period 1 minute.
52
+ * Default threshold: > 0.
53
+ *
54
+ * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/metrics-dimensions.html
55
+ */
56
+ writeThrottleEvents?: AlarmConfig | false;
57
+ }
58
+ //# sourceMappingURL=table-alarm-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-alarm-config.d.ts","sourceRoot":"","sources":["../../src/table-alarm-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;;;OAUG;IACH,YAAY,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAEnC;;;;;;;;;;OAUG;IACH,kBAAkB,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAEzC;;;;;;;;;OASG;IACH,mBAAmB,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;CAC3C"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=table-alarm-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-alarm-config.js","sourceRoot":"","sources":["../../src/table-alarm-config.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ import type { AlarmConfigDefaults } from "@composurecdk/cloudwatch";
2
+ interface TableAlarmDefaults {
3
+ enabled: true;
4
+ systemErrors: AlarmConfigDefaults;
5
+ readThrottleEvents: AlarmConfigDefaults;
6
+ writeThrottleEvents: AlarmConfigDefaults;
7
+ }
8
+ /**
9
+ * AWS-recommended default alarm configuration for DynamoDB tables.
10
+ *
11
+ * Thresholds are deliberately strict (> 0) because the metrics they watch —
12
+ * server-side errors and throttling — should be at or near zero for a healthy
13
+ * table. Tune them up via `recommendedAlarms` for workloads where a low rate
14
+ * of throttling is expected and acceptable (e.g. cost-optimised provisioned
15
+ * tables that lean on burst capacity).
16
+ *
17
+ * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#DynamoDB
18
+ */
19
+ export declare const TABLE_ALARM_DEFAULTS: TableAlarmDefaults;
20
+ export {};
21
+ //# sourceMappingURL=table-alarm-defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-alarm-defaults.d.ts","sourceRoot":"","sources":["../../src/table-alarm-defaults.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,UAAU,kBAAkB;IAC1B,OAAO,EAAE,IAAI,CAAC;IACd,YAAY,EAAE,mBAAmB,CAAC;IAClC,kBAAkB,EAAE,mBAAmB,CAAC;IACxC,mBAAmB,EAAE,mBAAmB,CAAC;CAC1C;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,EAAE,kBAqClC,CAAC"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TABLE_ALARM_DEFAULTS = void 0;
4
+ const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
5
+ /**
6
+ * AWS-recommended default alarm configuration for DynamoDB tables.
7
+ *
8
+ * Thresholds are deliberately strict (> 0) because the metrics they watch —
9
+ * server-side errors and throttling — should be at or near zero for a healthy
10
+ * table. Tune them up via `recommendedAlarms` for workloads where a low rate
11
+ * of throttling is expected and acceptable (e.g. cost-optimised provisioned
12
+ * tables that lean on burst capacity).
13
+ *
14
+ * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#DynamoDB
15
+ */
16
+ exports.TABLE_ALARM_DEFAULTS = {
17
+ enabled: true,
18
+ /**
19
+ * > 0 — any server-side (HTTP 500) error is an availability signal worth
20
+ * investigating. NOT_BREACHING for missing data: a table with no traffic
21
+ * emits no SystemErrors datapoints and should stay OK.
22
+ */
23
+ systemErrors: {
24
+ threshold: 0,
25
+ evaluationPeriods: 1,
26
+ datapointsToAlarm: 1,
27
+ treatMissingData: aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
28
+ },
29
+ /**
30
+ * > 0 — surface read throttling immediately. Conservative starting point;
31
+ * raise the threshold or `evaluationPeriods` for workloads where brief,
32
+ * self-correcting throttling under burst is tolerable.
33
+ */
34
+ readThrottleEvents: {
35
+ threshold: 0,
36
+ evaluationPeriods: 1,
37
+ datapointsToAlarm: 1,
38
+ treatMissingData: aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
39
+ },
40
+ /**
41
+ * > 0 — surface write throttling immediately, on the same basis as read
42
+ * throttling.
43
+ */
44
+ writeThrottleEvents: {
45
+ threshold: 0,
46
+ evaluationPeriods: 1,
47
+ datapointsToAlarm: 1,
48
+ treatMissingData: aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
49
+ },
50
+ };
51
+ //# sourceMappingURL=table-alarm-defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-alarm-defaults.js","sourceRoot":"","sources":["../../src/table-alarm-defaults.ts"],"names":[],"mappings":";;;AAAA,+DAA8D;AAU9D;;;;;;;;;;GAUG;AACU,QAAA,oBAAoB,GAAuB;IACtD,OAAO,EAAE,IAAI;IAEb;;;;OAIG;IACH,YAAY,EAAE;QACZ,SAAS,EAAE,CAAC;QACZ,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,iCAAgB,CAAC,aAAa;KACjD;IAED;;;;OAIG;IACH,kBAAkB,EAAE;QAClB,SAAS,EAAE,CAAC;QACZ,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,iCAAgB,CAAC,aAAa;KACjD;IAED;;;OAGG;IACH,mBAAmB,EAAE;QACnB,SAAS,EAAE,CAAC;QACZ,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,iCAAgB,CAAC,aAAa;KACjD;CACF,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { type Alarm } from "aws-cdk-lib/aws-cloudwatch";
2
+ import { type ITable } from "aws-cdk-lib/aws-dynamodb";
3
+ import type { IConstruct } from "constructs";
4
+ import type { AlarmDefinition } from "@composurecdk/cloudwatch";
5
+ import { AlarmDefinitionBuilder } from "@composurecdk/cloudwatch";
6
+ import type { TableAlarmConfig } from "./table-alarm-config.js";
7
+ /**
8
+ * Resolves the recommended alarm configuration into fully-resolved
9
+ * {@link AlarmDefinition}s for a DynamoDB table.
10
+ */
11
+ export declare function resolveTableAlarmDefinitions(table: ITable, config: TableAlarmConfig | undefined): AlarmDefinition[];
12
+ /**
13
+ * Creates AWS-recommended CloudWatch alarms for a DynamoDB table, merging
14
+ * recommended definitions with any custom alarm builders.
15
+ *
16
+ * @param scope - CDK construct scope for creating alarm constructs.
17
+ * @param id - Base identifier for alarm construct ids.
18
+ * @param table - The DynamoDB table to create alarms for.
19
+ * @param config - User-provided alarm configuration, or `false` to disable all.
20
+ * @param customAlarms - Custom alarm builders added via `addAlarm()`.
21
+ * @returns A record mapping alarm keys to their created Alarm constructs.
22
+ *
23
+ * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Best_Practice_Recommended_Alarms_AWS_Services.html#DynamoDB
24
+ */
25
+ export declare function createTableAlarms(scope: IConstruct, id: string, table: ITable, config: TableAlarmConfig | false | undefined, customAlarms?: AlarmDefinitionBuilder<ITable>[]): Record<string, Alarm>;
26
+ //# sourceMappingURL=table-alarms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-alarms.d.ts","sourceRoot":"","sources":["../../src/table-alarms.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,KAAK,EAKX,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,KAAK,MAAM,EAAa,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAoC,MAAM,0BAA0B,CAAC;AACpG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAyChE;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB,GAAG,SAAS,GACnC,eAAe,EAAE,CAqEnB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,UAAU,EACjB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB,GAAG,KAAK,GAAG,SAAS,EAC5C,YAAY,GAAE,sBAAsB,CAAC,MAAM,CAAC,EAAO,GAClD,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAUvB"}