Skip to content

Instantly share code, notes, and snippets.

@aruokhai
Last active July 23, 2026 13:04
Show Gist options
  • Select an option

  • Save aruokhai/ce35e2bdcf602d79434b6babc77d7322 to your computer and use it in GitHub Desktop.

Select an option

Save aruokhai/ce35e2bdcf602d79434b6babc77d7322 to your computer and use it in GitHub Desktop.
Simple Enclave AWS Cost

Enclave Platform — AWS Cost Analysis

A self-contained AWS cost analysis for one enclave deployment: the full detail of five areas — fixed infrastructure, usage-based infrastructure, the freshness anchor (S3), KMS key material, and state_root — followed by a consolidated, segmented monthly estimate for an example workload.

Headline: for the example workload (§7.1), $209/month ($2,510/year) for one host — ~68% is the always-on EC2 instance. Parts 1–5 detail each area; Part 7 consolidates them by cost behavior (fixed, variable, per-reboot, per-migration, genesis).

Contents


Part 0 — Method & master pricing

0.1 Scope and method

Costs are derived from the Terraform inventory and the runtime code paths. Prices are us-east-1, verified against AWS pricing pages in July 2026. Volume-driven lines are expressed as rates; absolute totals depend on the workload defined in §7.1. Excludes CloudTrail, cross-AZ transfer (single-AZ host), support plans, and taxes.

Conventions: 1 month = 730 hours; 1 year ≈ 3.156×10⁷ seconds.

0.2 Master pricing reference

Service Item Rate
EC2 m6i.xlarge on-demand $0.192 / hr ($140.16/mo)
EBS gp2 storage $0.10 / GB-month
Networking Public IPv4 (EIP or auto-assigned) $0.005 / hr ($3.65/mo)
Networking VPC interface endpoint $0.01 / hr / AZ ($7.30/mo) + $0.01/GB
Networking VPC gateway endpoint (S3, DynamoDB) $0
Networking Data transfer out to internet $0.09 / GB (first 10 TB; first 100 GB/mo free)
Route 53 Hosted zone $0.50 / zone / month
Route 53 Standard queries $0.40 / million
S3 Standard storage (first 50 TB) $0.023 / GB-month
S3 PUT / COPY / POST / LIST $0.005 / 1,000 ($5×10⁻⁶ each)
S3 GET / SELECT $0.0004 / 1,000 ($4×10⁻⁷ each)
DynamoDB On-demand write (WRU) $0.625 / million
DynamoDB On-demand read (RRU) $0.125/M strong; $0.0625/M eventual
DynamoDB Storage $0.25 / GB-month
DynamoDB Point-in-time recovery (PITR) $0.20 / GB-month
KMS Customer-managed key $1.00 / key / month
KMS Symmetric request $0.03 / 10,000 (20,000/mo free)
KMS Asymmetric request (reference) $0.15 / 10,000 (no free tier)
SSM Standard param + standard API $0
SSM Advanced param $0.05 / param / month
SSM Advanced API interactions $0.05 / 10,000
CloudWatch Logs Ingestion $0.50 / GB
CloudWatch Logs Storage $0.03 / GB-month
Other STS, KMS CreateKey/GetKeyPolicy, NSM, VPC/subnets/IGW/SG $0

The KV table is PAY_PER_REQUEST.


Part 1 — Fixed (static) infrastructure

Resources billed by the hour or month regardless of application traffic. Scope: one host (aws_instance.nitro, count = 1); multiply per-host lines by instance count for a fleet.

1.1 Summary

  • Fixed floor per deployment: $163/month ($1,957/year).
  • The EC2 Nitro host is ~86% of it.
  • No NAT gateway or load balancer is provisioned; egress uses an Elastic IP and AWS access uses VPC endpoints (two interface, one gateway).

1.2 Fixed-cost inventory

Resource Terraform Basis Monthly
EC2 Nitro host (m6i.xlarge, 24/7, enclave_options) aws_instance.nitro (:1257) instance-hour $140.16
Root EBS volume (32 GB gp2, encrypted) root_block_device (:1268) GB-month $3.20
Elastic IP / public IPv4 aws_eip.instance (:1342) IP-hour $3.65
VPC interface endpoint — KMS aws_vpc_endpoint.kms (:1138) endpoint-hour/AZ $7.30
VPC interface endpoint — SSM aws_vpc_endpoint.ssm (:1151) endpoint-hour/AZ $7.30
KMS key — PCR0 signing aws_kms_key.pcr0_signing (:424) key-month $1.00
Route 53 hosted zone (part of the enclave system) zone + aws_route53_record.enclave (:1359) zone-month $0.50
Total ~$163.11 / month

$0 (no charge): aws_vpc.main, three subnets (:1049/:1060/:1071), aws_internet_gateway.main (:1082), route tables, aws_security_group.nitro, and the S3 gateway endpoint aws_vpc_endpoint.s3 (:1164).

1.3 Notes

  • EC2 dominates (~$140 of ~$163). Instance type (var.instance_type, default m6i.xlarge, :93) scales it linearly; m6i.xlarge is 4 vCPU, the minimum practical size for Nitro Enclaves. Billed whenever running, independent of load.
  • Route 53 hosted zone is part of the enclave system, billed at $0.50/month; the A-record it holds is free. The record is attached via var.tls.route53_zone_id (:1360), so the zone is provisioned/owned within the deployment's account.
  • Interface endpoints are per-AZ. KMS and SSM endpoints are each in one subnet (:1143/:1156); adding AZs multiplies the $7.30 lines.
  • Elastic IP is billed while allocated, attached or not, at $0.005/hour. It is not extra cost over a public IP — since 2024 every public IPv4 is billed at that rate. It buys a stable address so the Route 53 record survives restarts and re-association on replacement.
  • Also fixed, detailed elsewhere in this document: runtime KMS keys (§4) and state_root receipts (§5).
  • Fleet scaling: EC2, EBS, and Elastic-IP are per host; endpoints, the hosted zone, and the signing key are per VPC/region and shared across hosts.

1.4 Network topology and the VPC-endpoints optimization

The host is in a public subnet (:1264) with an Elastic IP and an internet-gateway route (:1090), and open egress (aws_security_group_rule.all_egress, :1245). The two interface endpoints (KMS, SSM) cost $14.60/month and, in this topology, are removable (AWS calls fall back to the internet-gateway path, as DynamoDB/CloudWatch/STS already do) — a −$14.60/month optimization.


Part 2 — Variable (usage-based) infrastructure

Resources billed per request, per GB, or per operation, scaling with application traffic, KV writes, and log volume.

2.1 Inventory

Resource Terraform / source Basis Driver
Freshness anchor (S3) aws_s3_bucket.anchor PUT/LIST/storage KV writes — §3
CloudWatch Logs IAM logs:* on /enclave/*; groups at runtime ingestion + storage log verbosity × retention
Data-transfer egress instance public HTTPS listener GB out client response traffic
DynamoDB — KV aws_dynamodb_table.kv RRU/WRU (on-demand) KV ops + per-boot Scan
DynamoDB — state lock aws_dynamodb_table.lock RRU/WRU OpenTofu state locking (minimal)
Route 53 queries aws_route53_record.enclave per million DNS query volume
S3 — assets aws_s3_bucket.assets storage + GET EIF + supervisor binary (~constant); GET on boot
S3 — ACME cert cache aws_s3_bucket.storage (:796), used by runtime/acme_cache.go storage + requests TLS cert cache (autocert); a few KB, read on boot / written on issuance — negligible
S3 — OpenTofu state aws_s3_bucket.state storage + requests plan/apply frequency (minimal)
VPC endpoint data KMS/SSM interface endpoints per GB KMS/SSM payloads (small)
KMS requests runtime keys per 10k (20k/mo free) boots + migrations — §4

2.2 Main drivers

  • Freshness anchor (S3) — one locked PUT per KV write plus a full ListObjectVersions sweep per boot; the dominant variable line for a write-heavy app. Full model in §3.
  • CloudWatch Logs — ingestion $0.50/GB, storage $0.03/GB-month against the configured retention. Example: 10 GB/month ingested = $5.00 + $0.30/month.
  • Data-transfer egress — client response bytes at $0.09/GB after the first 100 GB/month (free). Example: 100 GB billable = $9.00.
  • DynamoDB (KV) — on-demand; scales with KV ops plus the per-boot Scan (§2.3). PITR adds continuous-backup storage proportional to table size.

2.3 DynamoDB boot Scan

Before the anchor runs, NewKVStore performs a full DynamoDB Scan to build the live version map. A filtered Scan still reads every item (heads + chunk rows) before filtering, so cost scales with total stored bytes, billed on every boot:

  • On-demand, eventually-consistent Scan = 0.5 RRU per 4 KB at $0.125/M RRU ≈ $0.015 per GB scanned. A 1 GB table ≈ $0.015/boot; a 1 TB table ≈ $15/boot.
  • Point-in-time recovery is enabled (cli/tofu_files.go:907), adding continuous-backup storage at $0.20/GB-month proportional to table size.

Part 3 — Freshness anchor (S3)

The anchor provides rollback detection: it writes one immutable, undeletable S3 object per KV version bump and, on every cold boot, lists the accumulated history to rebuild its version floor.

3.1 Mechanism

  • One object per version bump. write()/writeTombstone() commit to DynamoDB, then put a DEK-sealed CBOR object at anchor/<key>/<20-digit version>.
  • Immutable. Put with ObjectLockMode=Compliance, RetainUntilDate = now + window (anchor.go:132); anchorWindow() defaults to ~10 years.
  • No exit. No DeleteObject/BypassGovernanceRetention grant and no S3 lifecycle rule; the object set is append-only.
  • Boot rebuild. Establish() lists all anchors to compute a per-key version floor and halts if the live version is below any floor. The floor is in-memory only, rebuilt every boot.

3.2 Thesis: cost is decoupled from dataset size

The number of live keys and the number of lifetime writes are independent. The anchor reflects cumulative writes, not the current key count.

Symbol Meaning Grows with
T total in-window objects = Σ N_k cumulative lifetime writes (≈ all writes, 10-yr window)
K distinct KV keys in-window key cardinality
N_k versions of key k in-window write frequency of that key

T is monotonic within the window.

3.3 Unit economics — one anchor object

  • Measured object size ≈ 100 bytes (89–138 B; ~95–100 B for typical keys). Body = DEK.Seal(CBOR(anchorEntryV1)) = CBOR (~58 B fixed + key length + version bytes) + 29 B AEAD overhead (version(1)+nonce(12)+tag(16)).
  • Create = 1 PUT = $5×10⁻⁶.
  • Store one anchor for a year ≈ 100 B × $0.276/GB-yr ≈ $2.8×10⁻⁸ — a PUT costs ~180× one year of storing the object.

3.4 Write cost (PUT)

One PUT per version bump. Objects/year = rate × 3.156×10⁷.

Sustained write rate Objects / year Annual PUT cost
1 write/sec 31.6 M $158
10 writes/sec 316 M $1,578
100 writes/sec 3.16 B $15,780

3.5 Storage cost

At a rolling 10-yr window, steady-state object count = rate × 3.156×10⁸.

Write rate Steady-state objects (10 yr) Bytes @100 B Storage / yr (steady)
1 write/sec ~3.16 × 10⁸ ~31.6 GB $8.7
10 writes/sec ~3.16 × 10⁹ ~316 GB $87
100 writes/sec ~3.16 × 10¹⁰ ~3.16 TB $872

Caveats: (1) storage accrues linearly over the ramp, so cumulative 10-year spend is ~half the steady-state annual figure × 10; (2) without an S3 lifecycle rule, objects persist even after the 10-yr lock lapses, so storage grows unbounded — the steady-state figures hold only if paired with a post-expiry NoncurrentVersionExpiration/Expiration rule.

3.6 Boot read cost (LIST)

Establish() enumerates the anchor namespace twice (whole-anchor/ sweep + per-key sweep), 1000 objects/page. LIST/boot ≈ 2·T/1000 at $5×10⁻⁶ each, plus ~K GETs at $4×10⁻⁷.

Write rate T (10-yr steady) LIST req / boot Cost / boot
1 write/sec 3.16 × 10⁸ ~632 K ~$3.2
10 writes/sec 3.16 × 10⁹ ~6.3 M ~$32
100 writes/sec 3.16 × 10¹⁰ ~63 M ~$316

No checkpoint exists, so each boot repeats the full sweep. Per-boot cost × reboot frequency:

Reboot cadence → Monthly (12/yr) Weekly (52/yr) Daily (365/yr)
1 write/sec ($3.2/boot) $38 $164 $1,153
10 writes/sec ($32/boot) $379 $1,643 $11,534
100 writes/sec ($316/boot) $3,789 $16,432 $115,340

At 10 writes/sec with daily reboots, annual boot-listing ($11,534) is ~7× the annual PUT cost ($1,578). Each instance runs Establish independently, so a fleet of N instances multiplies the per-boot cost by N per deploy.

3.7 Retention-window comparison (1 / 2 / 5 / 10 yr)

The window (ENCLAVE_ANCHOR_WINDOW, default ~10 yr) sets steady-state object count = rate × window. It scales storage and boot-LIST linearly and leaves the PUT floor unchanged. Below at 10 writes/sec (316 M objects/yr):

Window Steady-state objects Storage / yr LIST / boot Boot LIST / yr (weekly)
1 yr ~3.16 × 10⁸ $8.7 ~$3.2 ~$164
2 yr ~6.32 × 10⁸ $17 ~$6.3 ~$329
5 yr ~1.58 × 10⁹ $44 ~$16 ~$822
10 yr (default) ~3.16 × 10⁹ $87 ~$32 ~$1,643

PUT cost is $1,578/yr in every row. Caveats: (1) the window alone does not cut storage — nothing deletes objects at expiry without a lifecycle rule; (2) a shorter window only works if still-live cold keys are re-anchored before their anchor expires, else their floor drops.


Part 4 — KMS key material

The KMS-managed key material: the Terraform PCR0-signing key, the runtime primary key, the storage DEK, static secrets, and migration keys.

4.1 Overview — envelope encryption

The enclave uses envelope encryption. KMS is called only at boot to unwrap the DEK (dek.go Seal/Open); every KV read/write and anchor seal is then a local AES-GCM operation with no KMS call. So KMS request volume is a function of boot and migration count, not write volume or dataset size. Only customer-managed keys (CMKs) carry the $1/month fee — the Terraform signing key, the runtime primary key, and each migration key; the storage DEK and static secrets are free data keys wrapped by a CMK.

4.2 AWS calls per boot

  • Steady-state resume boot (runtime.go:124FetchOrInitDEK; FetchOrInitStaticSecrets): 1 KMS Decrypt for the DEK (dek.go:64) + N KMS Decrypt, one per static secret (static_secret.go:84) → (1 + N) KMS requests. Plus GetKeyPolicy (free) and standard-tier SSM reads (free).
  • Genesis (first boot): CreateKey (free) + GenerateDataKey × (1 DEK + N secrets) + SSM writes. One-time.
  • Migration boot: additional CreateKey + DEK re-wrap (§4.5).

4.3 Per-boot request cost

Cost/boot = (1 + N) × $3×10⁻⁶:

Static secrets N KMS requests/boot Cost/boot Annual @ weekly boots (52)
0 1 $3×10⁻⁶ $0.0002
3 4 $1.2×10⁻⁵ $0.0006
10 11 $3.3×10⁻⁵ $0.002

At 10 secrets and weekly reboots, ~570 requests/year — far under the 20,000/month free tier, so the billed amount is $0. At the asymmetric rate ($0.15/10,000, no free tier), 570 requests/year is $0.009/year.

4.4 SSM parameter cost

Standard-tier params (key ID, DEK ciphertext, secret ciphertexts, metadata) are free. State-origin receipts use the advanced tier (state_origin.go:276, WithAdvancedTier()) because an NSM attestation document exceeds the 4 KB standard-tier limit — ~1–3 advanced params at $0.05/param/month. These are the same params detailed in §5; counted once.

4.5 The migration operation (one-time cost)

A migration (StartMigration, migrate.go:124) is performed by the running predecessor: it creates a new PCR0-locked key, re-encrypts every static secret and the storage DEK under it, and writes results + handoff receipts before flipping KMSKeyID. For N static secrets:

Step AWS call Count Billed
Create migration key kms.CreateKey (kms.go:304) 1 free (key then $1/mo — §4.6)
Caller identity sts.GetCallerIdentity 1 free
Re-encrypt each secret (verify round-trip) kms.Encrypt + kms.Decrypt 2 × N $0.03/10k, free-tier
Re-wrap DEK (ExportKey, verify round-trip) kms.Encrypt + kms.Decrypt 2 $0.03/10k, free-tier
Store re-wrapped secrets + DEK ssm.Set (standard) N + 1 free
Predecessor attestation ssm.Set advanced 1 +$0.05/mo param
Transition receipt ssm.Set advanced 1 +$0.05/mo param
Previous-PCR0 + flip KMSKeyID ssm.Set (standard) 2 free
Successor's first-boot state-origin receipt ssm.Set advanced 1 +$0.05/mo param

One-time cryptographic cost = (2N + 2) KMS requests × $3×10⁻⁶. At N = 10 that is 22 requests = $0.00007, within the free tier. Standard SSM writes are $0. The one-time charge for a migration is therefore $0; the recurring additions are the new key (+$1/month) and ~2–3 new advanced params (+$0.10–$0.15/month). Secrets are re-encrypted, not re-generated — the plaintext (and the app's env var) is unchanged; only the KMS wrapping moves to the new key.

4.6 Migration keys: growth and reclaim

Growth. Each migration mints a new CMK that becomes the successor's primary; the previous key is retained (its SSM DEK-ciphertext lineage persists and its policy admits the old PCR0 for rollback-to-self). Key count = 1 + retained migration keys, each $1/month. A migration is triggered by a PCR0 change (new enclave image), so without cleanup key count tracks deploy cadence:

Retained migrations (no cleanup) KMS keys Fixed $/yr
0 1 $12
5 6 $72
12 13 $156

Billing of cleanup: ScheduleKeyDeletion — a key pending deletion bills $0 during its 7–30 day window, then is gone; canceling re-bills the waiting days.

4.7 Scaling: large, long-lived deployment (with cleanup)

Assuming dead migration keys are cleaned up, retained key count is a small fixed set (current + predecessors in the rollback window). The recurring bill is then set by that count, not by migration cadence or secret count.

  • A static secret adds only free-tier work (+1 Decrypt/boot, +2 requests/migration).
  • A migration adds a key + receipts, but cleanup reclaims them once superseded.

Annual recurring cost, retaining 2 keys, cleanup keeping pace:

migrations / month ↓ \ static secrets → 5 25 100
1 $24 $24 $24
10 $24 $24 $24
30 $24 $24 $24

The surface is flat in both axes: migration cadence is reclaimed, and each secret's KMS traffic stays inside the free tier (exceeded only when boots×(1+N) + migrations×(2N+2) > 20,000/mo). The only knob is the rollback-retention count:

Recent keys retained Annual cost
1 (current only) $12
2 (current + 1) $24
3 $36
5 $60

Add ~10% for the matching advanced-tier receipts. Sizing rule: annual key-material cost ≈ $12 × retention count (+ ~10%), provided cleanup keeps pace.


Part 5 — State root

The state_root mechanism: a SHA-256 commitment over key-material artifacts, sealed into an NSM attestation receipt and used to classify and verify each boot (genesis / resume / migration).

5.1 Mechanism

stateRoot(keyID) builds a canonical CBOR pre-image over an artifact list, then a domain-separated SHA-256: kmsKeyIDParam value, each static secret's ciphertext param (SHA-256 of value), and the storage DEK ciphertext param (SHA-256). Pre-image size is O(secrets + 2); it excludes migration-predecessor params and commits no KV data or anchor state. The hash is sealed into a receipt (putReceipt) as the user_data of an NSM attestation document, stored base64 in an advanced-tier SSM param (the document exceeds the 4 KB standard-tier limit).

5.2 AWS calls per boot

Boot state SSM reads SSM advanced write KMS / S3 Per-boot cost
Resume receipt (advanced) + artifacts (standard) none none ~$1×10⁻⁵
Genesis artifacts (standard) 1 receipt none ~$5×10⁻⁶ + $0.05/mo param
Migration receipt + artifacts ~2 receipts none ~$1×10⁻⁵ + params

Verification is a local nsm.VerifyAttestation (state_origin.go:324), no AWS call. Advanced-tier interactions — reading the receipt on resume, writing new receipts on genesis/migration — bill at $0.05/10,000 ($5×10⁻⁶ each); standard-tier artifact reads (key ID, secrets, DEK) are $0. Genesis/migration also create $0.05/month advanced params (recurring — see §5.3).

5.3 Cost model

Secret count does not enter state_root cost — it produces one receipt document per key regardless of N, and the pre-image reads (key ID, secret ciphertexts, DEK) are standard-tier ($0). Two frequencies matter:

  • Migrations — recurring cost. One advanced-tier receipt param per retained KMS key at $0.05/month. Dominant term.
  • Reboots — interaction cost. Each resume boot reads the advanced-tier receipt (~1–2 advanced API interactions at $5×10⁻⁶ each). Sub-cent.

Recurring receipt storage (migration-driven):

Retained KMS keys Receipt params $/month $/year
1 (no migrations) 1 $0.05 $0.60
2 (cleanup keeps current + 1) 2 $0.10 $1.20
6 (5 retained) 6 $0.30 $3.60
13 (12 retained) 13 $0.65 $7.80

Full annual cost by migration × reboot frequency (cleanup keeping 2 keys):

Migration rate ↓ / Reboots → Weekly (52/yr) Daily (365/yr)
None $0.60 $0.60
1 / month $1.20 $1.20
1 / week $1.20 $1.20

The reboot column is effectively flat: even daily reboots add only ~365 × $1×10⁻⁵ ≈ $0.004/yr of advanced-read interactions, dwarfed by receipt storage. Migration frequency is the material axis, and with cleanup it is bounded by the retention count, not the rate (§4.7). Without cleanup the recurring term grows with migrations: 1/month → 13 receipts → $7.80/yr; 1/week → 53 receipts → ~$32/yr.

Bottom line: state_root ≈ $0.05/month × retained receipts. Migration frequency (× retention policy) is the only material driver; reboot frequency adds a sub-cent interaction cost; secret count is irrelevant.


Part 6 — Cross-subsystem view & appendices

6.1 Subsystem comparison

State root KMS key material Freshness anchor
Scales with write rate? No No Yes — O(cumulative writes)
Scales with dataset / boots? No No Yes
Per-boot AWS spend ~$0 (advanced read) ~$0 (free-tier KMS) $3–$316 (LIST)
Durable footprint 1 advanced SSM param / key $1/mo per KMS key 1 S3 object / write
Typical annual $ $0.60 $12–$36 $158 – $15,780+
Growth vector migrations (1 receipt/key) migrations (1 key/receipt set) KV writes

6.2 Optimizations

Optimization Effect Where
Remove redundant KMS/SSM interface endpoints −$14.60/month §1.4
Right-size / stop idle instances −$140/month per host §1.3
Schedule deletion of dead migration keys keeps key material flat (§4.7) §4.6
Add post-expiry S3 lifecycle rule on the anchor bucket caps anchor storage growth §3.5
Checkpoint the anchor floor (engineering change) collapses boot-LIST from O(T) §3.6
Shorten the anchor retention window (+ re-anchoring) reduces anchor storage + boot-LIST §3.7

6.3 Double-counting and free tiers

  • The state_root receipt (§5) and the static-keys advanced SSM param (§4.4) are the same object — counted once. KMS keys total 3 (1 signing + 2 retained runtime).
  • Free tiers applied: first 100 GB/month egress and 20,000/month KMS requests are free; the KMS-request line is $0 at the example scale.

6.4 Exclusions

CloudTrail, cross-AZ data transfer (single-AZ host), OpenTofu state bucket beyond nominal, support plans, and taxes.


Part 7 — Consolidated monthly estimate

7.1 Example workload ("average requirements")

Parameter Assumption
Hosts 1 × m6i.xlarge, 24/7, us-east-1
KV write rate ~1 write/sec average (~2.63 M/month)
KV read rate ~10 reads/sec average (~26.3 M/month)
KV dataset size 5 GB
Static secrets 3
Migrations ~1/month; cleanup retains 2 runtime keys
Reboots Weekly (~4/month)
Application age ~1 year (affects anchor storage + boot listing)
CloudWatch Logs 20 GB/month ingested, 30-day retention
Data egress 200 GB/month (100 GB billable after free tier)
DNS 1 Route 53 hosted zone, ~5 M queries/month

The two most uncertain inputs are read rate and log volume; both are covered in the sensitivity table (§7.4).

7.2 Monthly cost by segment

Costs are grouped by how they accrue: two continuous streams (fixed, variable) and three lifecycle events (reboot, migration, genesis). Event costs are per-occurrence × the example frequencies (§7.1).

Fixed — always-on, independent of usage:

Line Basis Monthly
EC2 m6i.xlarge (24/7) $0.192/hr × 730 $140.16
EBS root (32 GB gp2) $0.10/GB-mo $3.20
Public IPv4 (Elastic IP) $0.005/hr × 730 $3.65
VPC interface endpoints ×2 (KMS, SSM) $7.30 each $14.60
KMS keys ×3 (signing + 2 runtime) $1/key-mo $3.00
Route 53 hosted zone $0.50/mo $0.50
state_root receipts ×2 $0.05 each $0.10
Fixed subtotal $165.21

Variable — usage-driven, continuous:

Line Basis Monthly
Anchor PUT (2.63 M writes) $0.005/1k $13.14
Anchor storage (~3.2 GB, yr 1) $0.023/GB-mo $0.07
DynamoDB writes (2.63 M WRU) $0.625/M $1.64
DynamoDB reads (26.3 M RRU, strong) $0.125/M $3.29
DynamoDB storage (5 GB) $0.25/GB-mo $1.25
DynamoDB PITR backup (5 GB) $0.20/GB-mo $1.00
CloudWatch ingestion (20 GB) $0.50/GB $10.00
CloudWatch storage (20 GB) $0.03/GB-mo $0.60
Data egress (100 GB billable) $0.09/GB $9.00
Route 53 queries (5 M) $0.40/M $2.00
S3 misc (assets / ACME cache / state) storage + requests $0.50
VPC interface-endpoint data $0.01/GB $0.05
Variable subtotal $42.54

Per-reboot — event, ×4/month (weekly):

Line Per boot ×4/mo
Anchor boot-LIST (T ≈ 31.6 M) $0.316 $1.26
DynamoDB boot Scan (5 GB) $0.075 $0.30
state_root receipt read ~$1×10⁻⁵ ~$0
KMS Decrypts (1 + N) free tier $0
Reboot subtotal ~$0.39/boot $1.56

Per-migration — event, ×1/month:

Line Per migration Note
CreateKey + re-encrypt secrets/DEK ((2N+2) KMS req) free tier one-time ~$0
Receipt writes (~2–3 advanced) ~$1.5×10⁻⁵ one-time
Migration one-time ~$0 lasting cost = +$1.05/mo (1 key + receipt), carried in Fixed

Genesis — one-time (first boot): CreateKey + GenerateDataKey×(1+N) + initial receipt — all free-tier, ~$0 one-time. It establishes the recurring Fixed lines (keys, receipts).

Rollup:

Segment Monthly
Fixed (always-on) $165.21
Variable (usage) $42.54
Reboots (4/mo) $1.56
Migrations (1/mo) ~$0 one-time (recurring folded into Fixed)
Genesis ~$0 one-time
Total ≈ $209.31

The bill is ~79% continuous (fixed + variable); the event streams add only ~$1.56/month at these frequencies. Migration and reboot events are near-free per occurrence — migration's real cost is the recurring key + receipt it leaves behind (folded into Fixed), and reboot's is the anchor/DDB re-scan.

7.3 Cost distribution (by category)

Category Monthly Share
Compute (EC2 + EBS) $143.36 68.5%
Networking (IP, endpoints, DNS, egress) $29.80 14.2%
Storage & database (anchor, DynamoDB, S3) $22.45 10.7%
Logging (CloudWatch) $10.60 5.1%
Key management (KMS keys, receipts) $3.10 1.5%
Total $209.31 100%

At average request volumes the deployment is compute-bound: the single always-on instance is more than two-thirds of the bill. The four largest usage lines are anchor PUTs ($13), CloudWatch ingestion ($10), egress ($9), and DynamoDB reads ($3).

7.4 Sensitivity — how the estimate moves

Change from baseline Effect on monthly total
Write rate ×10 (10 writes/sec) Anchor PUT +$118, DynamoDB writes +$15, boot LIST grows → ≈ +$135
Read rate ×10 (100 reads/sec) DynamoDB reads +$30 → ≈ +$30
Log volume ×5 (100 GB/mo) CloudWatch +$40 → ≈ +$40
Egress ×5 (1 TB/mo) +$81 → ≈ +$81
Mature app (10-yr anchor accumulation, same 1 w/s) Boot LIST $1.26 → ~$12.6, storage +$0.7 → ≈ +$12
Reboot ×7 (daily instead of weekly) Reboot segment $1.56 → ~$11 → ≈ +$9
Migration ×30 (daily, no cleanup) +$30/mo of retained keys over a year → ≈ +$30
Fleet ×3 hosts (endpoints/DNS/keys shared) Compute + IP ×3 → ≈ +$294
Larger host (m6i.2xlarge) EC2 $140 → $280 → ≈ +$140

The dominant levers are host size/count (fixed) and, under heavy load, anchor writes and egress (variable).


pricing verified against AWS EC2, EBS, VPC, KMS, SSM, S3, DynamoDB, CloudWatch, Route 53, and data-transfer pricing pages (us-east-1, July 2026). Object sizes are measured. Absolute totals depend on the workload; the example assumptions in §7.1 define the headline estimate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment