This check flags DynamoDB Accelerator (DAX) clusters running without server-side encryption at rest. DAX caches sensitive table data in memory and on disk, so an unencrypted cluster leaves that data exposed. The catch: encryption can only be set at creation time, so you need to recreate the cluster with --sse-specification Enabled=true.
DynamoDB Accelerator (DAX) is an in-memory cache that sits in front of your DynamoDB tables to cut read latency from milliseconds to microseconds. It is great for read-heavy workloads, but it also means a copy of your table data now lives somewhere other than DynamoDB itself. If that cache is not encrypted at rest, you have quietly widened your attack surface.
The DAX Cluster Not Encrypted check looks at every DAX cluster in your AWS account and confirms that server-side encryption (SSE) is enabled. If it is not, the cluster is flagged.
What this check detects
DAX supports encryption at rest using AWS owned keys through SSE. When enabled, the data DAX stores on its underlying cluster nodes, including the cached item data and the change log, is encrypted on disk.
This check inspects the SSESpecification property of each DAX cluster. A cluster passes when SSE status is ENABLED and fails when it is DISABLED or absent.
Note: DAX encryption at rest protects data stored on the cluster's disks. It is separate from encryption in transit (TLS between your application and the DAX endpoint), which is also configurable but controlled independently.
Why it matters
People often assume that because DynamoDB encrypts data at rest by default, anything sitting in front of it inherits that protection. DAX does not. An unencrypted DAX cluster stores plaintext copies of your most frequently accessed items on EC2-backed nodes.
Here is where that bites you:
- Data sprawl. Your DynamoDB table might hold customer records, session tokens, or PII. DAX caches that exact data. If the source table is encrypted but the cache is not, you have an unencrypted copy of regulated data that auditors will absolutely find.
- Compliance gaps. Frameworks like PCI DSS, HIPAA, and SOC 2 expect encryption at rest for sensitive data everywhere it lives. An unencrypted cache is a finding waiting to happen, and "it's just a cache" is not a defense.
- Physical and snapshot exposure. Encryption at rest defends against scenarios where the underlying storage is accessed outside the normal API path. Without it, that layer of defense in depth is missing.
Warning: Because the cache mirrors your hottest data, an unencrypted DAX cluster is not a minor or theoretical exposure. It is often holding the exact records you most need to protect.
How to fix it
The important constraint: DAX encryption at rest can only be enabled when the cluster is created. There is no in-place toggle. To remediate an existing unencrypted cluster, you create a new encrypted one and migrate traffic to it.
Step 1: Confirm the current state
Check whether SSE is enabled on a cluster:
aws dax describe-clusters \
--cluster-names my-dax-cluster \
--query "Clusters[].{Name:ClusterName,SSE:SSEDescription.Status}" \
--output table
If the SSE column shows DISABLED or is empty, the cluster needs to be recreated.
Step 2: Create a new encrypted cluster
Create a replacement cluster with SSE enabled, reusing the same subnet group, parameter group, and IAM role as the original:
aws dax create-cluster \
--cluster-name my-dax-cluster-encrypted \
--node-type dax.r5.large \
--replication-factor 3 \
--iam-role-arn arn:aws:iam::123456789012:role/DAXServiceRole \
--subnet-group-name my-dax-subnet-group \
--security-group-ids sg-0abc123def456 \
--sse-specification Enabled=true
Match the --node-type and --replication-factor to your original cluster so capacity stays the same.
Step 3: Point your application at the new endpoint
Grab the new cluster endpoint and update your application configuration:
aws dax describe-clusters \
--cluster-names my-dax-cluster-encrypted \
--query "Clusters[0].ClusterDiscoveryEndpoint.Address" \
--output text
Roll out the new endpoint to your application. Because DAX is a cache, there is no data to migrate manually. The new cluster warms up from DynamoDB as requests flow through it.
Danger: Do not delete the old cluster until the new endpoint is fully live and serving traffic. Deleting the active cluster first will send all reads straight to DynamoDB and can spike your read capacity costs and latency.
Step 4: Decommission the old cluster
Once traffic is confirmed on the encrypted cluster, remove the old one:
aws dax delete-cluster --cluster-name my-dax-cluster
Doing it right the first time with Terraform
If you manage DAX with Terraform, enable encryption from the start so you never hit this finding:
resource "aws_dax_cluster" "main" {
cluster_name = "my-dax-cluster"
iam_role_arn = aws_iam_role.dax.arn
node_type = "dax.r5.large"
replication_factor = 3
subnet_group_name = aws_dax_subnet_group.main.name
security_group_ids = [aws_security_group.dax.id]
server_side_encryption {
enabled = true
}
}
Tip: In CloudFormation, set SSESpecification: { SSEEnabled: true } on the AWS::DAX::Cluster resource. Bake it into your module defaults so every new cluster is encrypted whether or not the author remembers to ask for it.
How to prevent it from happening again
Since you cannot fix encryption after the fact, prevention is where the real win is. Stop unencrypted clusters from ever reaching production.
Policy-as-code in CI/CD
Add a check to your pipeline that fails any plan creating a DAX cluster without SSE. With Checkov, the relevant rule is built in:
checkov -d . --check CKV_AWS_47
For OPA / Conftest against Terraform plan JSON, a minimal rule looks like this:
package main
deny[msg] {
rc := input.resource_changes[_]
rc.type == "aws_dax_cluster"
sse := rc.change.after.server_side_encryption
not sse[_].enabled
msg := sprintf("DAX cluster '%s' must have server-side encryption enabled", [rc.address])
}
Service Control Policies
At the organization level, you can deny the creation of DAX clusters that do not request encryption using an SCP condition on the API call:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyUnencryptedDAX",
"Effect": "Deny",
"Action": "dax:CreateCluster",
"Resource": "*",
"Condition": {
"Bool": {
"dax:SSEEnabled": "false"
}
}
}
]
}
Tip: Continuous checks in Lensix catch clusters that slip past CI, including ones created manually in the console or by a forgotten automation script. Pair a pipeline gate with ongoing scanning so nothing lives unencrypted for long.
Best practices
- Encrypt every DAX cluster by default. There is no cost to enabling SSE with AWS owned keys, and no performance penalty worth worrying about. Treat it as a non-negotiable baseline.
- Enable encryption in transit too. Encryption at rest covers stored data, but the connection between your application and DAX should use TLS. Configure the cluster endpoint encryption type and use the encrypted DAX client.
- Standardize on a module. Wrap DAX creation in a shared Terraform or CloudFormation module that hard-codes encryption. Individual teams should not be able to opt out by omission.
- Audit what you cache. Know which tables sit behind DAX and what data they hold. The sensitivity of the cache equals the sensitivity of the source table.
- Document the recreation runbook. Because remediation requires a new cluster, keep a tested migration procedure ready so fixing a finding is a quick, low-risk operation rather than a scramble.
Encryption at rest on DAX is one of those settings that costs nothing, takes one line of configuration, and is genuinely painful to add later. Set it once, enforce it in the pipeline, and let continuous monitoring catch the stragglers.

