The conventional wisdom says if a KMS key hasn't been used in six months, it's safe to delete. Just check the last-use timestamp, schedule the deletion, and move on to the next cost-saving task.
This approach sounds efficient. The GetKeyLastUsage API seems designed for this purpose. AWS even provides sample scripts that filter keys by idle periods and present them as deletion candidates. The logic appears airtight: unused keys cost money and expand your attack surface. Why keep them?
Why This Reasoning Fails
Last-use timestamps tell you when a key performed a cryptographic operation. They don't tell you whether the key protects data you still need.
Consider how Amazon EBS volumes work. When you attach an encrypted volume to an EC2 instance, the KMS key decrypts the data encryption key once. That plaintext key gets cached in the Nitro Card hardware. For months or years afterward, every read and write operation uses that cached key without touching KMS. Your production database could run continuously for 18 months with zero KMS API calls. The GetKeyLastUsage API would show no activity since the volume attached.
If you delete that key based on the timestamp, the volume keeps working. Your applications run normally. Everything looks fine until you need to restart the instance or reattach the volume. At that moment, you discover the encrypted data key stored with the volume can't be decrypted. The data becomes permanently inaccessible.
This isn't a theoretical edge case. It's how the service works by design.
Evidence From AWS's Own Implementation
The tracking period limitation reveals AWS's caution about this data. Tracking began on April 23, 2026, for most regions. A key created in January 2026 might have encrypted critical data in February and March, but that activity won't appear in the usage information. The API can't distinguish between "never used" and "used before we started counting."
Even AWS's sample script for identifying unused keys marks entries with an asterisk when no operations occurred since tracking started. That asterisk acknowledges that absence of evidence isn't evidence of absence.
The documentation explicitly warns: "The last usage information tells you when a key was last used, not whether it will be needed in the future." This isn't boilerplate legal language. It's recognition that cryptographic operations and data protection requirements operate on different timelines.
What To Do Instead
Build a three-layer verification process before scheduling any key deletion:
Layer one: Dependency mapping. Before checking timestamps, identify what the key protects. Query EBS volumes and snapshots associated with the key. Check S3 bucket encryption configurations. Review Lambda environment variables. Document RDS instances using the key for encryption at rest. This inventory tells you what breaks if the key disappears.
Layer two: Disable and monitor. Use DisableKey instead of ScheduleKeyDeletion. A disabled key can't perform new cryptographic operations, but it remains available for future decryption if needed. Run your applications for a full business cycle with the key disabled. Monitor CloudTrail for AccessDeniedException errors that indicate something tried to use the key.
Layer three: Policy controls. Implement the kms:TrailingDaysWithoutKeyUsage condition key in your key policies to prevent deletion of recently-used keys:
{
"Sid": "PreventDeletionOfRecentlyUsedKeys",
"Effect": "Deny",
"Principal": "*",
"Action": [
"kms:ScheduleKeyDeletion",
"kms:DisableKey"
],
"Resource": "*",
"Condition": {
"NumericLessThanEquals": {
"kms:TrailingDaysWithoutKeyUsage": "365"
}
}
}
This creates a mandatory waiting period based on actual usage, not just calendar time.
For cost optimization, focus on identifying keys that were created but never used for any cryptographic operation. These are genuinely safe deletion candidates. The GetKeyLastUsage API serves this purpose well when the TimeStamp field is empty and the key was created after the tracking start date.
Set up CloudWatch alarms that notify you if a key pending deletion receives any access attempts. This gives you the 7-30 day deletion waiting period to cancel if something unexpected surfaces.
When Last-Use Timestamps Matter
Last-use timestamps do matter for specific scenarios:
Compliance reporting. Auditors ask when encryption keys were last accessed. The GetKeyLastUsage API answers that question directly without requiring CloudTrail log analysis. This supports SOC 2 Type II evidence requirements around cryptographic key management.
Detecting anomalies. If a key that typically processes operations daily suddenly shows no activity for a week, that's a signal worth investigating. The application might have failed over to a different region, or a service might be down without triggering other alerts.
Rotation planning. Keys that see frequent use need different rotation schedules than keys used quarterly for specific batch processes. Usage patterns inform your key lifecycle policies.
The API provides valuable data. It just shouldn't be the sole input for deletion decisions. Treat it as one signal among several, weighted appropriately for the decision you're making. When the question is "Can we delete this?" the timestamp ranks below dependency mapping and disable testing. When the question is "Is this key behaving normally?" the timestamp becomes primary evidence.
Your key management strategy needs to account for the gap between cryptographic activity and data protection requirements. They're related but not identical, and that distinction determines whether your cost optimization initiative becomes a data loss incident.





