TableV2MultiAccountReplica: does not set top-level SSESpecification when using TableEncryptionV2.customerManagedKey(), causing deployment failure
#37783 opened on May 6, 2026
Description
Describe the bug
When using TableV2MultiAccountReplica with TableEncryptionV2.customerManagedKey(), the generated CloudFormation template is missing the top-level SSESpecification property on the AWS::DynamoDB::GlobalTable resource. This causes CloudFormation to fail with:
Resource handler returned message: "Invalid request provided: ReplicaSSESpecification and SSEType must be null when SSE is set to default."
Regression Issue
- Select this option if this issue appears to be a regression.
Last Known Working CDK Library Version
No response
Expected Behavior
The TableV2MultiAccountReplica construct should render a top-level SSESpecification with SSEEnabled: true and SSEType: "KMS" when using customer-managed key encryption, matching the behavior of TableV2:
{
"Type": "AWS::DynamoDB::GlobalTable",
"Properties": {
"TableName": "MyGlobalTable",
"GlobalTableSourceArn": "arn:aws:dynamodb:us-west-2:111111111111:table/MyGlobalTable",
"SSESpecification": { /* <=== this */
"SSEEnabled": true,
"SSEType": "KMS"
},
"Replicas": [{
"Region": "us-east-2",
"SSESpecification": {
"KMSMasterKeyId": "arn:aws:kms:us-east-2:222222222222:key/..."
}
}]
}
}
Current Behavior
TableV2MultiAccountReplica only sets SSESpecification.KMSMasterKeyId at the replica level, but omits the top-level SSESpecification entirely:
{
"Type": "AWS::DynamoDB::GlobalTable",
"Properties": {
"TableName": "MyGlobalTable",
"GlobalTableSourceArn": "arn:aws:dynamodb:us-west-2:111111111111:table/MyGlobalTable",
"Replicas": [{
"Region": "us-east-2",
"SSESpecification": {
"KMSMasterKeyId": "arn:aws:kms:us-east-2:222222222222:key/..."
}
}]
}
}
DDB's CFN validator has a rule that says "all settings must be null if SSE is disabled". This lack of SSESpecification at the top-level is being interpreted as SSEEnabled: false. Because the replicas themselves have encryption info, the validator fails.
This seems to be backed up in the docs for SSESpecification:
Specifies the settings to enable server-side encryption. These settings will be applied to all replicas. If you plan to use customer-managed KMS keys, you must provide a key for each replica using the ReplicaSpecification.ReplicaSSESpecification property.
Reproduction Steps
import * as cdk from 'aws-cdk-lib';
import { Stack } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import {
AttributeType,
Billing,
TableEncryptionV2,
TableV2,
TableV2MultiAccountReplica,
} from 'aws-cdk-lib/aws-dynamodb';
import { Key } from 'aws-cdk-lib/aws-kms';
const PRIMARY_ACCOUNT = '111111111111';
const PRIMARY_REGION = 'us-west-2';
const REPLICA_ACCOUNT = '222222222222';
const REPLICA_REGION = 'us-east-2';
class PrimaryTableStack extends Stack {
public readonly table: TableV2;
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const kmsKey = new Key(this, 'TableKey', { enableKeyRotation: true });
this.table = new TableV2(this, 'GlobalTable', {
tableName: 'MyGlobalTable',
partitionKey: { name: 'pk', type: AttributeType.STRING },
billing: Billing.onDemand(),
encryption: TableEncryptionV2.customerManagedKey(kmsKey),
});
}
}
class ReplicaTableStack extends Stack {
constructor(scope: Construct, id: string, primaryTable: TableV2, props?: cdk.StackProps) {
super(scope, id, props);
const kmsKey = new Key(this, 'TableKey', { enableKeyRotation: true });
// BUG: This generates CloudFormation without top-level SSESpecification
new TableV2MultiAccountReplica(this, 'GlobalTableReplica', {
replicaSourceTable: primaryTable,
encryption: TableEncryptionV2.customerManagedKey(kmsKey),
});
}
}
const app = new cdk.App();
const primaryStack = new PrimaryTableStack(app, 'PrimaryTableStack', {
env: { account: PRIMARY_ACCOUNT, region: PRIMARY_REGION },
});
new ReplicaTableStack(app, 'ReplicaTableStack', primaryStack.table, {
env: { account: REPLICA_ACCOUNT, region: REPLICA_REGION },
});
app.synth();
Possible Solution
The TableV2MultiAccountReplica doesn't have anything setting sseSpecification. TableV2 in the same file sets it here.
Additional Information/Context
I've been able to mitigate this with an escape hatch:
const cfnTable = replicaTable.node.defaultChild as CfnGlobalTable;
cfnTable.addPropertyOverride('SSESpecification', {
SSEEnabled: true,
SSEType: 'KMS',
})
AWS CDK Library version (aws-cdk-lib)
2.241.0
AWS CDK CLI version
2.241.0
Node.js Version
20.x
OS
macOs
Language
TypeScript
Language Version
No response
Other information
No response