---
title: AWS KMS Encryption Architecture (2026): The Per-Tenant CMK Trap, the 10,000 req/s Shared Quota, and When AWS-Owned Keys Win
description: Most KMS guides stop at "enable encryption." The architecture decision that actually bites is the key boundary: split one CMK into 3,200 per-tenant keys and you pay ~$3,200/mo in key storage alone while still sharing a single 10,000 req/s symmetric quota. Here is the decision matrix, the throttle math, and the encryption-context pattern that gives per-tenant isolation without per-tenant keys.
url: https://www.factualminds.com/blog/aws-kms-encryption-architecture-cmk-strategy-2026/
datePublished: 2026-06-04T00:00:00.000Z
dateModified: 2026-06-10T00:00:00.000Z
author: Palaniappan P
category: Security & Compliance
tags: aws-kms, encryption, security, kms, cost-optimization, aws
---

# AWS KMS Encryption Architecture (2026): The Per-Tenant CMK Trap, the 10,000 req/s Shared Quota, and When AWS-Owned Keys Win

> Most KMS guides stop at "enable encryption." The architecture decision that actually bites is the key boundary: split one CMK into 3,200 per-tenant keys and you pay ~$3,200/mo in key storage alone while still sharing a single 10,000 req/s symmetric quota. Here is the decision matrix, the throttle math, and the encryption-context pattern that gives per-tenant isolation without per-tenant keys.

**As of June 2026, the hard part of KMS is not turning on encryption — it is choosing the key boundary.** AWS managed keys (the `aws/<service>` aliases) have been a legacy type since 2021; new services default to AWS owned keys, and the active decision in front of most teams is how many customer-managed keys (CMKs) to create and where to draw the lines between them. Get that wrong in a multi-tenant system and you either overpay by thousands of dollars a month in key storage or you throttle your own production traffic. This post is the architecture layer that the "enable default encryption" checklists skip.

This is for platform engineers, security architects, and CTOs designing encryption for a multi-account or multi-tenant AWS estate. We model the cost and throttle math in a downloadable [KMS throttle + cost model CSV](https://bitbucket.org/baymail/factualminds-astro/src/main/examples/architecture-blog-2026/kms-encryption-architecture/kms-throttle-cost-model.csv), ship a [key-strategy decision matrix](https://bitbucket.org/baymail/factualminds-astro/src/main/examples/architecture-blog-2026/kms-encryption-architecture/key-strategy-decision-matrix.md), and include the [key-policy templates](https://bitbucket.org/baymail/factualminds-astro/src/main/examples/architecture-blog-2026/kms-encryption-architecture/key-policy-templates.md) for the pattern we recommend.

> **Benchmark pattern (not a cited client)** — A composite multi-tenant B2B SaaS: ~3,200 tenants, SSE-KMS on S3 for tenant document storage, ~40M KMS cryptographic requests/month at steady state, peaky 9–6 traffic. Modeled in the [cost CSV](https://bitbucket.org/baymail/factualminds-astro/src/main/examples/architecture-blog-2026/kms-encryption-architecture/kms-throttle-cost-model.csv): one-CMK-per-classification (3 keys) runs ~$123/mo all-in; one-CMK-per-tenant (3,200 keys) runs ~$3,320/mo for the _same_ request volume — the extra ~$3,200/mo is pure key-storage tax. Turning on S3 Bucket Keys drops the request portion from ~$120/mo to ~$1.80/mo by cutting request volume ~99%. None of those three changes the shared 10,000 req/s symmetric quota.

## The decision is the key boundary, not the algorithm

KMS gives you three ownership tiers, and the cost/control trade-off is stark:

| Tier                                  | When to use                                                | Cost                               | You can audit/rotate? |
| ------------------------------------- | ---------------------------------------------------------- | ---------------------------------- | --------------------- |
| **AWS owned key**                     | Encryption-by-default, no need to control or audit the key | $0                                 | No                    |
| **AWS managed key** (`aws/<service>`) | Legacy; _no new ones created since 2021_                   | $0 storage, per-request billed     | View only             |
| **Customer managed key (CMK)**        | You need policy, rotation, deletion, audit, or grants      | $1/key/mo + rotation + per-request | Yes                   |

**Opinionated take:** default to **AWS owned keys** for convenience workloads, and step up to a **CMK only when you can name the control you need** — a specific key policy, a rotation cadence a regulator demands, an audit requirement, BYOK, or grant-based delegation. "We should use CMKs everywhere for security" is how teams end up with thousands of unaudited keys that satisfy no actual requirement.

Once you are on CMKs, the boundary question is where the money and the throttling live.

## The per-tenant CMK trap

The instinct in multi-tenant systems is one key per tenant — it _feels_ like stronger isolation. Two things make it the wrong default:

1. **Cost scales linearly with tenant count.** Every CMK is $1/month to exist, plus up to $2/month if you rotate it (first and second rotation each add $1; the AWS KMS pricing page has current numbers). At 3,200 tenants that is ~$3,200/month before a single `Decrypt`.
2. **It does not buy you throughput.** This is the part that surprises people.

KMS request-rate quotas are enforced **per account + per Region + per key type — not per key.** In most Regions the _Cryptographic operations (symmetric) request rate_ is **10,000 requests/second shared** across _every_ symmetric CMK in that account and Region, HMAC keys included. (RSA keys share a separate 1,000 req/s pool; ECC/SM2 share their own; all are Region-dependent and adjustable except the CloudHSM key store quota.) AWS's own example: at a 10,000 req/s symmetric quota, 9,500 `GenerateDataKey` + 1,000 `Encrypt` requests in one second gets throttled because together they exceed the shared pool.

So splitting one CMK into 3,200 per-tenant keys does **not** give you 3,200 × 10,000 req/s. Every call still draws from the same 10,000 req/s account+Region pool. You bought the storage bill of 3,200 keys and none of the throughput you imagined.

> **What broke** — A batch re-encryption job (key-rotation hygiene, rewriting ~9M S3 objects over a weekend) ran on a shared classification CMK with no data key caching. It generated ~14,000 `GenerateDataKey` req/s at peak against a 10,000 req/s symmetric quota. KMS returned `ThrottlingException`, the job's retry logic hammered the quota harder, and SSE-KMS-backed S3 reads for _live tenant traffic_ — which share the same quota — started failing with 503s. Detected via a CloudWatch alarm on KMS `ThrottlingException` count plus a spike in S3 5xx. Fix that worked overnight: throttled the batch job to 6,000 req/s, enabled data key caching for the re-encrypt path (cut `GenerateDataKey` ~90%), and added S3 Bucket Keys to the buckets. The "per-tenant keys would have isolated this" instinct is wrong — per-tenant keys share the same quota; only caching, Bucket Keys, or a quota increase actually move the ceiling.

## Tenant isolation without per-tenant keys

You get the same cryptographic isolation guarantee from **one classification CMK + encryption context**:

- Encrypt every object with `EncryptionContext={"tenant": "<tenant-id>"}`.
- Scope each tenant's IAM role with a condition on `kms:EncryptionContext:tenant` (pin it to a principal tag so you never rewrite the key policy per tenant).
- A cross-tenant decrypt fails because the context does not match — and every `Decrypt` in CloudTrail records the tenant value, which is a cleaner audit artifact than reconciling policy across thousands of keys.

The full key policy for this pattern (plus the per-tenant fallback for when a contract forces it) is in the [key-policy templates](https://bitbucket.org/baymail/factualminds-astro/src/main/examples/architecture-blog-2026/kms-encryption-architecture/key-policy-templates.md).

## Pick the coarsest boundary that meets the requirement

| Boundary                                                            | Keys at scale | Throttle exposure | Use when                                                 |
| ------------------------------------------------------------------- | ------------- | ----------------- | -------------------------------------------------------- |
| **One CMK per data classification** (`pii`, `financial`, `default`) | 3–6/account   | Low               | **Default.** Tenant isolation via encryption context     |
| **One CMK per account/stage**                                       | 1 per account | Low               | The account already _is_ the isolation boundary          |
| **One CMK per tenant**                                              | thousands     | High              | A contract/regulator names per-tenant keys, or true BYOK |
| **One CMK per resource**                                            | unbounded     | Very high         | Almost never                                             |

The classification boundary doubles as your `DataClass` tag value, which keeps your encryption model and your cost-allocation model aligned.

## Cut request cost before you cut control

Two levers move the request bill (and the throttle risk) without weakening the trust model:

- **S3 Bucket Keys** — turn on for every SSE-KMS bucket. AWS documents up to **99%** reduction in KMS request volume by collapsing per-object `GenerateDataKey` calls into per-bucket-key calls. This is the single highest-ROI KMS change for object-storage-heavy workloads, and it is a config flag, not a re-architecture.
- **Data key caching** (AWS Encryption SDK) — reuse a data key across many messages/objects, bounded by a max age and max message count. Cuts the `GenerateDataKey` rate — the operation most likely to throttle — while keeping envelope encryption. The trade-off is a slightly wider blast radius per data key, which you bound with conservative cache limits.

Do **not** "reduce costs" by disabling encryption or dropping to SSE-S3 where a CMK is actually required for audit or BYOK — Bucket Keys get you most of the savings without that loss of control.

## Multi-Region keys and custom key stores — only when the requirement is explicit

- **Multi-Region keys**: bill _per replica_ ($1/mo each), so a primary + two replicas is $3/mo per logical key. Use them for cross-Region DR of encrypted data or global tables — not as a default.
- **CloudHSM key store**: a dedicated single-tenant FIPS HSM inside AWS. Its request quota is **non-adjustable**, so size it deliberately and keep high-volume workloads on native KMS.
- **External key store (XKS)**: key material outside AWS, double encryption, **symmetric only**. AWS documents poorer latency, durability, and availability than native KMS. Worth it only when a regulator or contract requires keys outside AWS.

## What to do this week

1. Inventory your CMKs. Count keys per account+Region and tag each with the requirement that justifies it. Any CMK you cannot map to a control (policy/rotation/audit/BYOK/grant) is a candidate to collapse into a shared classification key or downgrade to an AWS owned key.
2. Run the [quota check script](https://bitbucket.org/baymail/factualminds-astro/src/main/examples/architecture-blog-2026/kms-encryption-architecture/check-kms-request-quota.sh) (read-only) to see your symmetric request-rate quota and your recent peak. If peak is within ~70% of the quota, you are one batch job away from throttling production.
3. Turn on **S3 Bucket Keys** on every SSE-KMS bucket. This is usually the biggest single cost and throttle win.
4. Replace any per-tenant CMK scheme that exists "for isolation" (not for contract) with one classification CMK + encryption context. Use the [key-policy templates](https://bitbucket.org/baymail/factualminds-astro/src/main/examples/architecture-blog-2026/kms-encryption-architecture/key-policy-templates.md).
5. Add a CloudWatch alarm on KMS `ThrottlingException` count _before_ your next bulk re-encryption or migration job, not after.

## What this post doesn't cover

- **Client-side envelope encryption internals** and the full AWS Encryption SDK keyring model — referenced here only as a request-rate lever.
- **Post-quantum cryptography in KMS** (ML-KEM / ML-DSA) — covered separately in [AWS KMS post-quantum cryptography](/blog/aws-kms-post-quantum-cryptography-ml-kem-ml-dsa/).
- **Secrets vs keys** — when to use Secrets Manager or Parameter Store instead of a KMS key directly; see [Secrets Manager vs Parameter Store](/blog/aws-secrets-manager-vs-parameter-store-when-to-use-which/).
- **DynamoDB and RDS at-rest specifics** beyond the key-boundary decision.
- **Exact current pricing** — always confirm per-key and per-request numbers on the AWS KMS pricing page; the figures here are the mid-2026 model.

---

**Related:** [AWS EBS encryption and KMS key lifecycle](/blog/aws-ebs-encryption-snapshot-hygiene-kms-lifecycle/) · [IAM least-privilege access control](/blog/aws-iam-best-practices-least-privilege-access-control/) · [Data residency and sovereignty](/blog/aws-data-residency-sovereignty-guide-2026/) · [AWS cloud security](/services/aws-cloud-security/)

**If you only do one thing:** Turn on S3 Bucket Keys on every SSE-KMS bucket today, then run the quota check script to see how close your peak request rate is to the shared symmetric ceiling. Those two facts decide whether your encryption architecture is one batch job away from throttling production.

## FAQ

### Does giving each tenant its own KMS key improve security or scalability?
It improves neither by default, and it hurts both economically. KMS request-rate quotas are enforced per account + per Region + per key type — not per key. In most Regions the symmetric cryptographic-operations quota is 10,000 requests/second shared across every symmetric customer-managed key (CMK) in that account and Region. Splitting one CMK into 3,200 per-tenant keys does not multiply that quota; every GenerateDataKey, Decrypt, and Encrypt call still draws from the same 10,000 req/s pool. Meanwhile you now pay roughly $3,200/month in key-storage charges before a single cryptographic operation. The same cryptographic isolation can be achieved on a shared classification key using encryption context — encrypt with EncryptionContext={tenant: id} and scope each tenant role to its own context value. Reserve per-tenant CMKs for cases where a contract or regulator explicitly names them, or for true bring-your-own-key.

### When should we NOT use a customer-managed KMS key?
Skip customer-managed keys (CMKs) when you do not need to control the key policy, rotation cadence, deletion, audit trail, or grants. For encryption-by-default workloads where convenience matters more than control, AWS owned keys cost nothing, require no management, and still encrypt your data — the trade-off is that you cannot audit, rotate, or delete them, and you cannot share data encrypted under them across accounts. Reach for a CMK only when you can name the specific control you need. Note that AWS managed keys (the aws/<service> aliases) are a legacy type AWS stopped creating for new services in 2021; new services default to AWS owned keys.

### What causes KMS ThrottlingException and how do we fix it?
ThrottlingException means you exceeded the per-account, per-Region, per-key-type request-rate quota in a one-second window — most commonly the shared symmetric quota (typically 10,000 req/s, Region-dependent and adjustable). The usual culprit is a batch job: a re-encryption pass, a bulk export, or an S3 workload generating per-object GenerateDataKey calls. Three fixes, in order of preference: (1) turn on S3 Bucket Keys, which can cut SSE-KMS request volume by up to 99% by reducing per-object calls to per-bucket-key calls; (2) add data key caching via the AWS Encryption SDK to reuse data keys and cut GenerateDataKey rate; (3) only if neither is acceptable for your data-handling rules, request a Service Quotas increase — but note that more requests means more per-request cost.

### How much does a KMS customer-managed key actually cost in 2026?
As of mid-2026, each customer-managed key costs $1/month (prorated hourly) for existence, regardless of whether it is symmetric, asymmetric, HMAC, multi-Region (each primary and each replica is billed), imported-material, or backed by CloudHSM or an external key store. Automatic or on-demand rotation adds $1/month for the first rotation and $1/month for the second in a given month; subsequent rotations that month are free. On top of storage you pay per cryptographic request (the free tier covers 20,000 requests/month across all Regions; some asymmetric operations are excluded). The request charge is what makes per-object S3 encryption expensive at scale and why S3 Bucket Keys matter. Always confirm current numbers on the AWS KMS pricing page.

### What is an external key store (XKS) and when is it worth the latency cost?
An external key store lets KMS use key material held in a key manager outside AWS, producing double encryption (KMS key material then the external key). It is worth it only when a regulator or contract requires that keys live outside AWS or under a dedicated HSM you control. The cost is operational: XKS supports symmetric keys only (no asymmetric, HMAC, or imported material), and AWS documents that keys in an external key store can have poorer latency, durability, and availability than native KMS keys because they depend on components outside AWS. If you only need a dedicated single-tenant FIPS HSM inside AWS, a CloudHSM key store is the lighter-weight choice — but its request quota is non-adjustable, so size it deliberately.

### Do per-tenant KMS keys help us prove tenant isolation to an auditor?
They can, but encryption context on a shared key proves the same property with a cleaner audit story. With encryption context, every Decrypt in CloudTrail records the tenant value, and a cross-tenant decrypt attempt fails because the context does not match the caller is authorized for — that is a demonstrable, logged isolation control. Per-tenant keys give you a per-key policy to point at, but at thousands of tenants the key sprawl becomes its own audit liability (rotation status, deletion windows, and policy drift across thousands of keys). Most auditors accept context-based isolation; confirm with yours before committing to per-tenant keys purely for the audit narrative.

---

*Source: https://www.factualminds.com/blog/aws-kms-encryption-architecture-cmk-strategy-2026/*
