DynamoDB tables are encrypted by default, but this encryption is managed by AWS, not by you.
Here’s how you can take control and encrypt your DynamoDB tables at rest using AWS Key Management Service (KMS).
Let’s say you’re building a new application and need a DynamoDB table to store user profiles. You want to ensure this data is encrypted when it’s not actively being used, sitting on disk.
aws dynamodb create-table \
--table-name UserProfiles \
--attribute-definitions \
AttributeName=UserId,AttributeType=S \
--key-schema \
AttributeName=UserId,KeyType=HASH \
--provisioned-throughput \
ReadCapacityUnits=5,WriteCapacityUnits=5 \
--sse-specification \
Enabled=true,KMSMasterKeyId=arn:aws:kms:us-east-1:123456789012:key/your-kms-key-id
When you run this create-table command, notice the --sse-specification argument. This is where the magic happens. Enabled=true tells DynamoDB that Server-Side Encryption (SSE) should be active. The KMSMasterKeyId points to the specific KMS key that will be used to encrypt and decrypt your data.
If you’re updating an existing table, you’d use update-table:
aws dynamodb update-table \
--table-name UserProfiles \
--sse-specification \
Enabled=true,KMSMasterKeyId=arn:aws:kms:us-east-1:123456789012:key/your-kms-key-id
This tells DynamoDB to start encrypting data for the UserProfiles table using the specified KMS key.
The core problem this solves is data security at rest. If someone were to gain unauthorized access to the underlying storage infrastructure where your DynamoDB data resides, without the KMS key, that data would be an unreadable jumble. The encryption is handled by DynamoDB itself, but the key used for that encryption is managed by you through KMS.
Internally, when you enable SSE with a KMS key, DynamoDB performs the encryption and decryption operations. It doesn’t store the plaintext data directly. Instead, it encrypts the data using a data key, and that data key is then encrypted by your KMS master key. This is a common pattern called "envelope encryption." DynamoDB handles the lifecycle of these data keys. When you request data, DynamoDB retrieves the encrypted data, uses your KMS master key to decrypt the data key, and then uses the data key to decrypt the actual data before returning it to you.
The primary lever you control here is the KMSMasterKeyId. You can choose to use an AWS-managed KMS key (where AWS creates and manages the key for you, and DynamoDB uses a specific alias like alias/aws/dynamodb) or a customer-managed KMS key (where you create, manage, and control the lifecycle of the key). Using a customer-managed key gives you more granular control over access policies and key rotation.
To check the encryption status of your table, you can use describe-table:
aws dynamodb describe-table --table-name UserProfiles --query SSEDescription.Status
This will output ENCRYPTED if SSE is enabled. If you want to see which KMS key is being used, you’d query SSEDescription.KMSMasterKeyArn.
The most surprising thing about this process is that even though DynamoDB handles the encryption/decryption, the performance impact is negligible for most workloads. DynamoDB is designed to integrate tightly with KMS, and these operations are highly optimized. You’re not paying a significant performance penalty for this enhanced security.
If you later decide you no longer need to encrypt your table with your specific KMS key, you can disable SSE. However, you cannot revert an encrypted table to unencrypted; you can only switch to using the AWS-owned KMS key (alias/aws/dynamodb).
The next concept you’ll likely encounter is managing the access policies for your KMS keys to ensure only authorized AWS services and IAM users/roles can use them for encryption and decryption.