Skip to content
CopyLocker

Cost Estimation

A usage model for the Cloudflare bill of a self-hosted CopyLocker server — 100k active devices validating daily under $20/month.

A usage model for the Cloudflare bill of a self-hosted CopyLocker server. The design constraint is NFR-COST-001: 100,000 active devices per month, each validating once per day, must cost under $20/month.

Scale assumptions

Following the roadmap-scale assumption behind NFR-COST-001:

VariableSymbolDefault
Active devices / monthD100,000
Validations per device per dayV1
Days / month30
Activations per device per monthA0.05 (1 per 20 devices)
Validation payload≤ 8 KB up / ≤ 12 KB down (NFR-PERF-010)
Audit/telemetry events per validationE~1

Derived monthly volumes:

Text
validations/month = D × V × 30 = 3,000,000activations/month = D × A = 5,000requests/month ≈ validations + activations ≈ 3.0 Mqueue ops/month ≈ requests × E × 3 (produce + consume + retry headroom)

Cost model by service

Formulas use placeholder unit prices (marked ~). Paid-plan baselines (e.g. Workers Paid at ~$5/month) are excluded — this models usage charges only.

Workers (requests)

Most validation traffic should resolve at the edge: public keysets and revocation data are KV-cached, and Cache/KV short-circuits everything that does not need a Durable Object (NFR-COST-002).

Text
worker_requests = requests/monthcost ≈ worker_requests × ~$0.30 / 1M ≈ 3.0M × $0.30/1M ≈ $0.90

CPU time matters more than request count at this scale: signing is < 3 ms CPU (NFR-PERF-009) and validation is signature verification plus KV reads, comfortably inside the included CPU allowance of the paid plan at millions of requests.

Durable Objects

Only stateful operations hit DOs: activations, seat changes, issuance, admin mutations. Validations are designed to be served from KV.

Text
do_requests = activations + admin_ops + seat_events ≈ 10⁴–10⁵ / monthcost ≈ do_requests × ~$0.15 / 1M + duration_gb_s × ~$12.50 / 1M GB-s ≈ cents

Duration stays negligible because DO requests are short (single-digit ms) and infrequent. Watch this term if you enable heartbeats at short intervals — heartbeat traffic lands here unless deliberately cached.

D1

D1 is written through the outbox projection (batched by the queue consumer) and read by the Admin API — not by validation traffic.

Text
d1_rows_read ≈ admin reads + projection bookkeeping ≈ 10⁶d1_rows_written ≈ activations + license/admin mutations + projections ≈ 10⁵–10⁶cost ≈ reads × ~$0.001 / 1M + writes × ~$1.00 / 1M ≈ $1

KV

Text
kv_reads ≈ validations (keyset/revocation lookups) ≈ 3.0 Mkv_writes ≈ epoch rotations + revocation batches + key rebuilds ≈ 10²–10³cost ≈ kv_reads × ~$0.50 / 1M ≈ $1.50

Queues

Audit and telemetry events flow through the queue in batches to R2 (NFR-COST-003) — never as high-frequency D1 writes.

Text
queue_ops ≈ events × ~3 (produce/consume/retry headroom) ≈ 9 Mcost ≈ queue_ops × ~$0.40 / 1M ≈ $3.60

R2

Immutable audit/event archive. Storage is the dominant term; Class A/B operations are minor at batch sizes.

Text
storage ≈ events/month × ~1 KB × retention_months ≈ 3M × 1KB × 12 ≈ 36 GB after a yearcost ≈ storage × ~$0.015 / GB-month + operations ≈ $0.54

R2 has no egress fees, which is what makes long audit retention cheap.

Secrets Store

Secrets Store is free at this scale; ignore it.

Rollup (defaults above)

Service≈ $/month
Workers0.90
Durable Objects< 0.10
D11.00
KV1.50
Queues3.60
R20.54
Total≈ $7.6

Against the $20 budget (NFR-COST-001) that leaves ~2.5× headroom for retries, admin traffic, growth, and price drift. The sensitive terms, in order: Queues (event fan-out E — batch aggressively), KV reads (scales with validations), D1 writes (keep projections batched).

Keeping it true

  • Cache short-circuits are the design (NFR-COST-002): if validation traffic starts hitting DOs or D1, cost and latency both degrade — treat that as a bug.
  • Batch through the Queue (NFR-COST-003): audit/telemetry must never become per-request D1 writes.
  • The requirements call for a copylocker-cli estimate --devices N --interval D command (NFR-COST-004) — not yet implemented; until it ships, this page's formulas are the estimator.