You open Cost Explorer this morning and see a $12 KMS charge. You don't remember creating any keys. Maybe you spun up an AWS service a few months back and forgot about it. Maybe a CloudFormation template you deployed created a customer managed key without making it obvious. Either way, that charge is real and it will keep appearing every month.
AWS KMS pricing has two components: a flat $1/month per customer managed key, plus API call charges beyond the 20,000 free requests per month. The key storage cost is what catches people off guard, because several AWS services create keys on your behalf without an explicit "you will now be charged $1/month" warning.
This guide covers the full AWS KMS pricing model, explains exactly where surprise charges come from, and gives you Terraform and CDK code to optimize your bill. All pricing data is sourced from the official AWS KMS pricing page and current as of March 2026, including the May 2024 key rotation pricing update. You can also use the AWS KMS Pricing Calculator to model your specific configuration.
Why You Might Be Seeing Unexpected KMS Charges
This is the question that brings most people to this page. Two re:Post community threads rank in the top 10 for "aws kms pricing" specifically because this question goes unanswered everywhere else. Let me answer it directly.
As of 2021, AWS stopped creating AWS managed keys (the free kind) for new services. Services launched after that point either use AWS owned keys (completely free, not visible in your account) or require you to create a customer managed key. Some services fall into a third category: they create a customer managed key automatically as part of their setup flow, burying the creation in a CloudFormation stack you didn't write yourself.
That CMK costs $1/month from the moment it's created. If you stop using the service and delete the stack, the key may not be deleted with it - it sticks around, billing silently until you find it.
Services That Silently Create Customer Managed Keys
Not every service does this, but these are the common culprits I've seen trigger surprise bills:
- AWS Backup with air-gapped vaults: air-gapped backup vaults require a customer managed key for encryption. When you create one, AWS Backup creates or prompts you to specify a CMK. If you tested this feature and forgot, that key is still there.
- CloudFormation solution templates: AWS solutions like the AWS Instance Scheduler, AWS Data Replication Hub, and others ship with CloudFormation templates that include
AWS::KMS::Keyresources. You deploy the solution, you get a key. - Third-party Marketplace products: many Marketplace offerings deployed via CloudFormation include KMS key resources in their templates.
- AWS services pre-2021 with managed key patterns: some older service integrations still create keys in your account under
aws/servicenamealiases.
The key detail: even if you stop using the service, the key keeps billing until you explicitly schedule it for deletion. That's the $1/month you can't explain.
How to Find All KMS Keys Across Your Regions
The KMS console is region-specific, which means you have to check each region manually - or use the CLI. Here's the approach I'd take:
# List all KMS keys in a specific region
aws kms list-keys --region us-east-1
# Loop across all regions to get a full picture
for region in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
echo "=== $region ==="
aws kms list-keys --region $region --query 'Keys[].KeyId' --output text
done
Once you have a list of key IDs, check their state and metadata:
aws kms describe-key --key-id <key-id> --region <region>
Look at KeyMetadata.KeyState (Enabled, Disabled, PendingDeletion) and KeyMetadata.Description for clues about what created it.
For tracing the origin of a key, go to CloudTrail and search for CreateKey events. The userIdentity field shows you exactly which IAM role, service, or user created it - which will usually point you straight to the CloudFormation stack or service responsible.
To understand which operations are driving your API call charges, go to Cost Explorer, filter by Service = "AWS Key Management Service", and group by "API Operation". That tells you whether the charges are from GenerateDataKey, Decrypt, or something else - which narrows down which workload is responsible. For teams tracking CloudTrail-related charges too, the CloudTrail Pricing Calculator covers that side of things.
What It Costs to Keep vs. Delete a Key
A few important cost facts about key lifecycle:
- Keys scheduled for deletion: $0 during the waiting period (7 to 30 days; default is 30 days). You can set the minimum to 7 days via
pendingWindowin CDK ordeletion_window_in_daysin Terraform. - Disabled keys: still $1/month. Disabling a key prevents it from being used for cryptographic operations, but it still exists and still bills. Disabled does not mean free.
- If you cancel a scheduled deletion: the key is billed as if the deletion was never scheduled - so those "free" waiting period days don't apply.
Before deleting any key, check CloudTrail for recent activity to confirm nothing is still using it. Deleting a key that still protects data makes that data permanently inaccessible. The 7-30 day waiting period is AWS's safety net for exactly this reason.
Now that you know where surprise charges come from, here's the full pricing model.
AWS KMS Pricing at a Glance (Quick Reference)
AWS KMS pricing breaks down into key storage and API usage. Here's the complete reference table:
| Pricing Component | Rate |
|---|---|
| Customer managed key (any type) | $1.00/month (prorated hourly) |
| First key rotation in a month | +$1.00/month |
| Second key rotation in a month | +$1.00/month |
| Third+ rotation in same month | Free |
| Multi-region replica key | $1.00/month each |
| AWS managed key storage | Free |
| AWS owned key storage | Free |
| Symmetric API calls (beyond free tier) | $0.03 per 10,000 requests |
| Asymmetric API calls | $0.15 per 10,000 requests |
| Free tier | 20,000 requests/month |
| CloudHSM custom key store | $1.60/HSM/hour (minimum 2 HSMs) |
| Key scheduled for deletion | Free during waiting period |
Two things in this table tend to surprise people: the rotation cost cap (covered in detail below), and the fact that asymmetric operations cost 5x more than symmetric. Use the AWS KMS Pricing Calculator to plug in your specific key count and API volumes for a personalized estimate.
Understanding KMS Key Types and Their Pricing Impact
The single biggest source of confusion in KMS billing is conflating two different concepts: who manages the key, and what cryptographic algorithm the key uses. These are independent dimensions with different cost implications.
The management tier (customer managed, AWS managed, or AWS owned) determines your storage cost. The key spec (symmetric vs. asymmetric) determines your API call cost. A customer managed asymmetric key costs $1/month in storage AND $0.15/10,000 on API calls. Get both wrong and you'll pay more than you need to.
Customer Managed Keys ($1/month)
You create these. You control them. You pay for them.
The $1/month storage fee applies regardless of key spec - symmetric AES-256, asymmetric RSA or ECC, HMAC, multi-region, or imported key material. Every customer managed key is $1/month flat. They count against your account quota (default 100,000 CMKs per region, adjustable via Service Quotas).
Use customer managed keys when you need: custom key policies, cross-account encryption access, control over rotation schedule, BYOK (Bring Your Own Key) with imported material, or full CloudTrail audit of individual key usage. For teams using centralized identity and access management, CMKs are typically required for cross-account encryption workflows.
If none of those requirements apply to your workload, you might not need a CMK at all.
AWS Managed Keys (Free Storage, Billed API Calls)
These appear in your KMS console under "AWS managed keys" with aliases like aws/ebs, aws/s3, aws/rds. AWS creates them in your account when a service uses them for the first time.
No $1/month storage fee - but API calls are still billed to your account at the same rates as customer managed keys. The important constraint: you can't share them across accounts, can't write custom key policies, and can't control the rotation schedule (they auto-rotate annually).
AWS stopped creating new AWS managed keys for services launched after 2021. Newer services either use AWS owned keys or require you to create a CMK.
AWS Owned Keys (Completely Free)
These don't appear in your console at all. AWS manages them in a service account, not yours. DynamoDB uses AWS owned keys by default. Many Lambda environment variable encryption scenarios use them too.
No storage fee, no API call charges, no CloudTrail visibility. The trade-off is exactly that: no visibility, no custom policies, no audit trail. For most default-encryption use cases where you don't need audit or policy control, this is the right choice.
API Request Pricing: Where the Real Costs Hide
Key storage is predictable. API calls are where bills get out of hand.
Every encrypt, decrypt, and data key generation call to KMS counts against your monthly request total. The 20,000 free requests per month sounds like a lot until you realize that a single S3 bucket with per-object KMS encryption can blow past that in hours on a busy day. Understanding S3 pricing when using SSE-KMS encryption alongside KMS costs gives you the full picture of what object-level encryption actually costs.
For CloudTrail data event logging, high-volume KMS operations generate their own CloudTrail entries - a separate cost that compounds at scale.
The Symmetric vs. Asymmetric 5x Price Difference
This is the most actionable cost difference in KMS pricing:
- Symmetric key operations (Encrypt, Decrypt, GenerateDataKey, ReEncrypt, GenerateRandom, GenerateMac, VerifyMac): $0.03 per 10,000 requests
- Asymmetric key operations (Sign, Verify, Encrypt/Decrypt on RSA or ECC keys, GetPublicKey on asymmetric keys): $0.15 per 10,000 requests
That's a 5x price difference. At 1,000,000 operations per month:
- Symmetric: 1,000,000 / 10,000 x $0.03 = $3.00
- Asymmetric: 1,000,000 / 10,000 x $0.15 = $15.00
Asymmetric keys are required only when encryption must happen outside AWS (using a downloaded public key), for digital signing (RSA-PSS, ECDSA, ML-DSA), or for key agreement via ECDH. For data encryption within AWS services - EBS, S3, RDS, DynamoDB - symmetric keys are the right choice. Always.
A common mistake I see: creating an RSA key for general-purpose data encryption because it "feels more secure." Symmetric AES-256 in KMS is equally secure for in-AWS workloads and costs 5x less to operate.
What's Included (and Excluded) in the Free Tier
The 20,000 free requests per month apply across all regions in your account - not 20,000 per region. And there are explicit exclusions:
Included in free tier: Encrypt, Decrypt, GenerateDataKey, ReEncrypt, GenerateRandom, GenerateMac, VerifyMac (when using symmetric or HMAC keys)
Excluded from free tier: GenerateDataKeyPair, GenerateDataKeyPairWithoutPlaintext, and any of Sign/Verify/Encrypt/Decrypt/GetPublicKey when called with asymmetric keys
A developer with a few EBS volumes and light S3 usage will likely never leave the free tier. A multi-tenant SaaS with per-object S3 encryption will exceed 20,000 requests before the first day of the month is over.
Which AWS Services Generate KMS API Calls
The call volume varies dramatically by service:
| Service | KMS Integration Pattern | Call Volume |
|---|---|---|
| Amazon S3 (SSE-KMS) | GenerateDataKey per write + Decrypt per read | Very high (per-object) |
| Amazon EBS | ~3 calls on volume creation, then at attach/detach | Low (stays in free tier for most workloads) |
| AWS Secrets Manager | Decrypt call on every GetSecretValue | Medium to high depending on retrieval frequency |
| Amazon SQS (SSE-KMS) | GenerateDataKey per message without caching | Very high for busy queues |
| Amazon DynamoDB | AWS owned key by default - zero calls | Zero unless you add a CMK |
| Amazon RDS | Relatively infrequent, storage-level encryption | Low |
The practical takeaway: S3 and SQS are the two services most likely to drive your KMS API bill into meaningful territory. EBS almost never does.
Key Rotation Costs: The 2024 Update You Might Have Missed
If you've read other articles about KMS key rotation costs - especially anything written before mid-2024 - some of what you read is now outdated.
Before May 2024, each key rotation added $1/month indefinitely. A key rotated annually would cost $1/month in year 1, $2/month in year 2, $3/month in year 3, and so on forever. Some articles described this as "compounding rotation costs" and treated it as a significant long-term cost driver.
In May 2024, AWS capped the rotation charge: only the first and second rotation in a calendar month add $1/month each. Subsequent rotations in the same month are free. This eliminates the infinite growth scenario entirely.
How the New Rotation Cap Works
The cap applies per key, per calendar month. In practice:
- If you're on the default annual rotation schedule (one rotation per year), you will almost never hit two rotations in the same month. The cap primarily matters for aggressive on-demand rotation scenarios.
- AWS managed keys rotate annually at no charge. The rotation pricing only applies to customer managed keys.
- Asymmetric keys, HMAC keys, and keys with imported key material cannot use automatic rotation at all.
- On-demand rotation is capped at 25 per key total - a hard limit that cannot be increased via Service Quotas.
Rotation is supported on customer managed symmetric keys with AWS_KMS origin, and for multi-region keys (rotation enabled on the primary key syncs the setting to all replicas).
Year-by-Year Cost Projection for Auto-Rotation
With annual rotation and the current pricing cap:
| Year | Rotation Events | Monthly Key Cost |
|---|---|---|
| Year 1 (creation, no rotation yet) | 0 | $1.00 |
| Year 2 (first rotation) | 1 | $2.00 |
| Year 3+ (second rotation, then capped) | 2 | $3.00 max |
For comparison, before the May 2024 update, Year 4 would have been $4/month, Year 5 = $5/month, and so on. The cap eliminates that growth. A key held for 10 years with annual rotation now costs a predictable $3/month at steady state, not $10/month.
The minimum rotation period is 90 days, maximum is 2,560 days. The default is 365 days.
Multi-Region Key Pricing: The $1/Month Per Replica Surprise
Multi-region keys allow the same key material to exist in multiple AWS regions under the same key ID. This means you can encrypt data in us-east-1 and decrypt it in eu-west-1 without re-encrypting or making cross-region API calls to KMS.
The pricing catch: every replica key is another $1/month, billed separately. A key present across three regions costs $3/month in base storage (1 primary + 2 replicas). At year 3+ steady state with annual rotation, the primary key reaches $3/month and each replica adds $1/month, bringing the total to $5/month for that single logical key. And that's before any API call charges in each region.
Multi-region keys cannot be created in a custom key store (CloudHSM or XKS). And critically: you must designate a key as multi-region at creation time. You cannot convert a single-region key to multi-region after the fact.
Disaster Recovery Scenarios and What They Cost
Here are concrete cost projections for common multi-region setups in multi-account AWS Organizations:
Active-passive DR (2 regions): primary in us-east-1, replica in us-west-2
- Base storage: $2/month (primary + 1 replica)
- Year 3+ steady state with annual rotation: $4/month ($3 primary + $1 replica)
3-region active-active: primary in us-east-1, replicas in eu-west-1 and ap-southeast-1
- Base storage: $3/month (primary + 2 replicas)
- Year 3+ steady state with annual rotation: $5/month per logical key ($3 primary + $1 per replica)
These numbers are for key storage only. API call charges in each region are billed separately to the account making the call in that region. A read-heavy replica in eu-west-1 serving millions of decryption requests will add significant API call charges on top of the $1/month storage.
The use cases that justify multi-region keys: disaster recovery where the recovery region must be able to decrypt without cross-region KMS calls, global active-active applications with distributed readers, and client-side encryption workloads with geographically distributed users.
Real-World KMS Cost Examples
The abstract pricing model is useful, but here's what actual bills look like for specific architectures.
These scenarios use the official AWS pricing examples as a base and extend them with realistic workload numbers. For a personalized calculation, the AWS KMS Pricing Calculator lets you model your exact key count and API volumes.
Startup: S3 Encryption Before and After Bucket Keys
Scenario: small SaaS, 1 CMK, 500,000 S3 object writes per month, 2,000,000 reads per month.
Without S3 Bucket Keys (one KMS call per S3 object operation):
- Key storage: $1.00
- API calls: 2,500,000 total - 20,000 free = 2,480,000 paid
- 2,480,000 / 10,000 x $0.03 = $7.44
- Monthly total: $8.44
With S3 Bucket Keys enabled (KMS calls batched at bucket level, ~99% reduction):
- Key storage: $1.00
- API calls: ~25,000 total - 20,000 free = 5,000 paid
- 5,000 / 10,000 x $0.03 = $0.02
- Monthly total: ~$1.02
Savings: $7.42/month. A single bucket_key_enabled = true line in your Terraform config.
Mid-Size SaaS: 20 CMKs with Auto-Rotation
Scenario: 20 customer managed keys (one per major workload), all with annual auto-rotation enabled, at steady state after year 2 (each key has accumulated 2 rotation versions = $3/month each), moderate API usage staying within the free tier.
- Key storage at steady state: 20 keys x $3.00 = $60/month
- API calls: within free tier = $0
That's $720/year just in key storage. The insight here: key sprawl is expensive. If security policy allows consolidating from 20 to 8 keys (shared per environment or domain), you save $36/month ($432/year) with no change to your encryption posture.
Free-Tier User: One Silently Created CMK
Scenario: new AWS account, deployed the AWS Instance Scheduler solution from the AWS solutions library. The CloudFormation template includes a AWS::KMS::Key resource that gets created automatically.
- Cost: $1/month (API calls stay within the free tier)
- Annualized: $12/year
This is the "$12 charge I can't explain" that sends people to re:Post forums. The fix:
- Find the key in KMS console (or via
aws kms list-keys) - Check CloudTrail for the
CreateKeyevent and confirm Instance Scheduler created it - Verify whether the solution actually requires a CMK or can use an AWS managed key
- If the key is unnecessary, schedule deletion (7-day minimum waiting period, $0 during wait)
Enterprise: CloudHSM Custom Key Store
Scenario: compliance-driven workload requiring customer-controlled HSM hardware, same S3 workload as the startup example, CloudHSM custom key store with 2 HSMs (minimum for HA) running for a 31-day month in us-east-1.
- 1 KMS key: $1.00
- API calls: $7.44
- 2 HSMs x 24 hours x 31 days x $1.60/HSM/hour = $2,380.80
- Monthly total: $2,389.24
CloudHSM adds approximately $2,381/month in base infrastructure cost alone. Standard KMS already uses FIPS 140 Level 3 certified HSMs - the difference with a CloudHSM custom key store is that you control the HSM hardware. Reserve this option for compliance frameworks that explicitly require "Hold Your Own Key" (HYOK) with customer-controlled hardware. For most FIPS 140 Level 3 requirements, standard KMS already qualifies.
How to Reduce Your AWS KMS Bill
The good news: most KMS bills have at least one high-impact optimization available, and the top ones require minimal implementation effort.
Enable S3 Bucket Keys (Terraform + CDK Examples)
This is the highest-impact KMS optimization available, and it's a one-property change. S3 Bucket Keys work by generating a short-lived bucket-level key from KMS, storing it temporarily in S3, and using it to generate per-object data keys - eliminating per-object KMS round trips. AWS's own documentation says this reduces SSE-KMS costs by up to 99%.
Terraform:
resource "aws_s3_bucket_server_side_encryption_configuration" "example" {
bucket = aws_s3_bucket.example.id
rule {
apply_server_side_encryption_by_default {
kms_master_key_id = aws_kms_key.app_key.arn
sse_algorithm = "aws:kms"
}
bucket_key_enabled = true # Up to 99% fewer KMS API calls
}
}
CDK (TypeScript):
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as kms from 'aws-cdk-lib/aws-kms';
const key = new kms.Key(this, 'AppKey', {
enableKeyRotation: true,
});
const bucket = new s3.Bucket(this, 'EncryptedBucket', {
encryptionKey: key,
bucketKeyEnabled: true, // Up to 99% fewer KMS API calls
});
Important caveats before you enable this:
- Objects already in the bucket are not retroactively covered. Use S3 Batch Operations with
CopyObjectto re-encrypt existing objects with the bucket key. - Incompatible with DSSE-KMS (dual-layer server-side encryption).
- CloudTrail behavior changes: logs will show the bucket ARN instead of the object ARN. If your IAM or key policies use object ARN as the encryption context, they will break - switch to bucket ARN.
- Works with both customer managed keys and the AWS managed S3 key (
aws/s3), but you need a customer managed key for cross-account access or custom key policies.
Choose Symmetric Keys Over Asymmetric Where Possible
The 5x cost difference ($0.03 vs $0.15 per 10,000 calls) is significant at any meaningful scale. Before creating an asymmetric key, confirm you actually need one:
- You need to encrypt data outside AWS using the public key? Asymmetric key required.
- You need digital signing (RSA-PSS, ECDSA, ML-DSA post-quantum)? Asymmetric key required.
- You need ECDH key agreement? Asymmetric key required.
- You're encrypting data within AWS services? Use a symmetric key.
Audit and Delete Unused Keys
A disabled key is not a free key. It still bills $1/month. The audit process is straightforward:
# Check key state across a region
aws kms list-keys --region us-east-1 | jq -r '.Keys[].KeyId' | \
xargs -I {} aws kms describe-key --key-id {} --region us-east-1 \
--query 'KeyMetadata.{ID:KeyId, State:KeyState, Description:Description}' \
--output table
Before scheduling deletion on any key, check CloudTrail for recent usage. A 90-day lookback is a reasonable safety window. If a key shows no GenerateDataKey, Decrypt, or Encrypt events in 90 days, it's a strong candidate for deletion.
Keys scheduled for deletion incur no charges during the waiting period. If something breaks after scheduling, you can cancel within the window.
Use Data Key Caching for High-Volume Workloads
If you're doing client-side encryption with the AWS Encryption SDK, data key caching is the equivalent of S3 Bucket Keys for application-layer encryption. The SDK reuses data keys across multiple encryption operations within configurable bounds: max age, max bytes encrypted, and max messages.
This is particularly effective for SQS message encryption and stream processing workloads where you're encrypting thousands of messages per second. Without caching, each message triggers a GenerateDataKey call. With caching, one call serves thousands of messages within the cache window.
The trade-off: a compromised cached data key can decrypt more data within the cache period. Tune the TTL and byte limits according to your threat model - shorter windows reduce risk, longer windows reduce cost.
Set Up Cost Alerts with AWS Budgets
Create a cost budget in AWS Budgets scoped to the KMS service with a threshold 20% above your expected monthly spend. This catches key sprawl before it compounds. For teams with multiple AWS accounts, set budgets per account for KMS specifically.
In Cost Explorer, filtering by Service = "AWS Key Management Service" and grouping by "API Operation" tells you exactly which operations (GenerateDataKey, Decrypt, Sign) are driving charges - which points you to the specific workload to optimize.
AWS KMS vs. Azure Key Vault vs. GCP Cloud KMS Pricing
If you're evaluating KMS against other providers or running a multi-cloud architecture, here's a direct comparison. AWS figures are from the research-backed sources above; Azure and GCP figures are from their respective current official pricing pages.
| Feature | AWS KMS | Azure Key Vault | GCP Cloud KMS |
|---|---|---|---|
| Key storage (standard) | $1.00/month per CMK | ~$0.04/month per key version (Software) | $0.06/month per active key version |
| Symmetric API calls | $0.03/10,000 | ~$0.03/10,000 | $0.03/10,000 |
| Asymmetric API calls | $0.15/10,000 | ~$0.15/10,000 | $0.15/10,000 |
| HSM-backed option | Yes (CloudHSM, $1.60/HSM/hr) | Yes (Premium tier, $5/key/month) | Yes (Cloud HSM, $2.00/key/month) |
| Free tier | 20,000 requests/month | None | None |
The headline number (AWS KMS key storage at $1/month vs. Azure's ~$0.04/month or GCP's $0.06/month) makes AWS look more expensive for key storage. But the free tier for API calls and the 100+ native service integrations make KMS the only practical choice for AWS-native workloads. You'd pay far more in integration complexity and operational overhead trying to use an external key manager for EBS, RDS, and S3 encryption than the $1/month difference in key storage.
For AWS-native teams, this comparison is mostly useful for making the case internally that KMS is the right tool - not for finding a cheaper alternative.
Key Takeaways
AWS KMS pricing is simpler than it looks once you separate the two components:
- $1/month flat per customer managed key - the predictable, unavoidable part for any key you create or that gets created on your behalf.
- API call charges beyond 20,000 free/month - the variable part, driven almost entirely by which services are using your keys and at what volume.
Unexpected charges almost always come from one of three things: a CMK created by a CloudFormation solution template you deployed and forgot about, S3 per-object KMS calls without S3 Bucket Keys enabled, or key sprawl from multiple CMKs accumulating rotation versions over time.
The May 2024 rotation pricing cap means older articles warning about ever-growing rotation costs are outdated. At annual rotation, a key reaches its maximum storage cost of $3/month after year 2 and stays there.
For S3 workloads, enabling S3 Bucket Keys is the single most impactful optimization available - up to 99% reduction in API call costs with a one-property change. Always use symmetric keys for in-AWS data encryption. And run a periodic audit with aws kms list-keys across your regions to catch orphaned keys before they become a year's worth of unexplained $1/month charges.
If you're working on a broader AWS cost optimization strategy, KMS is typically a small line item - but the surprise charges are disproportionate to their size because they're so hard to trace without knowing where to look.
What's the weirdest KMS charge you've tracked down? A CMK from a service you didn't know created one, or something else entirely? Share in the comments below.
Catch KMS Cost Changes Before They Hit Your Bill
CloudBurn analyzes your Terraform and AWS CDK changes, showing encryption cost estimates directly in pull requests. Spot expensive key configurations during code review, not when the invoice arrives.