Chapter 25 · Cost Engineering, Quotas, Limits, Billing, and Capacity/Usage Forecasting
Model Cost per User / Feature / Event and Compare Denormalization, Fan-Out, Aggregation, and Retention Alternatives
Build feature-level unit economics for denormalization, fan-out, materialized aggregation and retention alternatives under realistic AtlasMart traffic.
1. AtlasMart architecture review: optimize cost per business event
Two teams submit different data models. Model A normalizes product/seller/order data and performs more reads. Model B duplicates display fields into order lines, seller summaries and feeds, increasing writes and storage. Asking “which model is cheaper?” without a workload is meaningless. The right unit is cost per business event at a stated traffic distribution.
- Build per-user/per-feature/per-event unit economics before producing a monthly total.
- Compare normalization, denormalization, fan-out, materialized aggregation and retention as workload tradeoffs.
- Keep Standard operation counts and Enterprise byte units in separate ledgers.
- Use sensitivity analysis to identify the assumptions that dominate cost.
- Reject cost optimizations that violate latency, consistency, security or recovery requirements.
Use the Emulator Suite, a Firebase demo project, or an isolated test project for destructive, security-sensitive, billing-sensitive, migration, backup/restore, or write-heavy exercises unless the lesson explicitly marks managed verification as required. Treat shown output as expected evidence unless it is explicitly identified as captured output, and re-check current Firebase/Google Cloud edition, mode, quota, pricing, and security documentation before production execution.
AtlasMart keeps project ID
demo-atlasmart-firestore, Standard-edition Native
mode, database (default), Node.js 22+, Firebase
CLI course baseline 15.30.0, Firebase JavaScript
SDK 12.19.0, Firebase Admin Node SDK
14.4.0 (with
@google-cloud/firestore 9.1.0), Firestore
emulator 127.0.0.1:8080, Auth emulator
127.0.0.1:9099, and Emulator UI
127.0.0.1:4000. Mandatory exercises are
local/no-cost and measure application operation counts, bytes,
retry assumptions, listener events and forecast arithmetic—not
production billing or capacity. Dated concrete USD examples
use on-demand us-central1 prices observed on 17
September 2026; always re-check the official pricing page,
your billing currency/SKU and discounts before a real
decision. Enterprise examples are analytical unless you
explicitly provision a billed Enterprise database.
2. Define five AtlasMart business events
| Feature/event | Representative work to model | Hidden dimension |
|---|---|---|
| Browse page | 24 product docs + tenant/category query/index work | Cache hit ratio, repeated refresh, index-entry reads. |
| Cart mutation | Cart document update + maybe inventory read | Retries/contention; document size growth. |
| Order placement | Order + lines + inventory + idempotency/audit writes | Transaction retries, fan-out/index writes. |
| Realtime order status | Initial result + status changes over listener lifetime | Reconnects and update rate. |
| Semantic product search | kNN index scan + returned docs | Vector index entries/bytes scanned and embedding/index storage. |
3. Cost per event is a vector, not a scalar
const event = { documentReads: 0, indexReadCharges: 0, documentWrites: 0, documentDeletes: 0, enterpriseReadUnits: 0, enterpriseWriteUnits: 0, enterpriseRealtimeUnits: 0, storageByteDays: 0, outboundBytes: 0, backupByteDays: 0, pitrByteDays: 0};export function scale(perEvent, eventsPerMonth) { return Object.fromEntries(Object.entries(perEvent) .map(([k,v]) => [k, v * eventsPerMonth]));}
Keep this vector through the architecture comparison. Convert to dollars only after aggregation. That makes it obvious whether a design wins by reducing reads while losing on writes/storage, or vice versa.
4. Denormalization: buy reads with writes and storage
Suppose AtlasMart copies sellerName,
productTitle and a thumbnail into every order line.
Order-history screens avoid additional product/seller reads and
remain historically stable, but a seller rename does not
automatically propagate. If business semantics require
historical snapshots, that duplication is not merely a
performance hack—it is the correct model. If semantics require
live names everywhere, the same duplication creates fan-out
update work.
| Alternative | Read effect | Write/storage effect | Correctness question |
|---|---|---|---|
| Reference live product/seller | More point reads or backend join-like orchestration | Less duplication | Should historical order text change when catalog changes? |
| Snapshot fields in order line | Fewer reads on order history | Larger order writes + storage/index entries | Are fields immutable historical facts? |
| Materialized seller dashboard | Cheap/fixed dashboard reads | Write fan-out and idempotent maintenance | How stale may the dashboard be? |
| On-demand aggregation | No materialized summary writes | Index scan/read cost at query time | Can latency/deadline handle dataset growth? |
5. Materialized aggregation: frequency decides the winner
A dashboard count computed once per hour may be cheaper and simpler as a server aggregation. The same count requested every second by thousands of users may justify a materialized counter despite extra writes. Model reads avoided per update, not ideology.
function compare({dashboardReads, aggregationReadCharges, sourceEvents, counterWritesPerEvent}) { return { onDemandReadCharges: dashboardReads * aggregationReadCharges, materializedReads: dashboardReads, // one summary document each materializedWrites: sourceEvents * counterWritesPerEvent };}console.table([ compare({dashboardReads:100, aggregationReadCharges:8, sourceEvents:50_000, counterWritesPerEvent:1}), compare({dashboardReads:1_000_000, aggregationReadCharges:8, sourceEvents:50_000, counterWritesPerEvent:1})]);
6. Retention changes both storage and query shape
Chapter 21 showed that TTL is lifecycle policy, not a scheduler. Here quantify its effect: shorter retention can reduce primary/index/PITR/backup footprint and scan work, but only if product/compliance rules allow deletion. Archive can shift cost rather than eliminate it. A right-to-delete workflow must account for primary data, retained backups/exports and documented recovery semantics rather than simply deleting the live document.
7. Mandatory lab: three traffic levels, four architecture alternatives
| Scenario | Daily active users | Browse/day/user | Cart mutations/day/user | Orders/day/user | Live status changes/order |
|---|---|---|---|---|---|
| Small | 1,000 | 3 | 1.5 | 0.12 | 3 |
| Growth | 10,000 | 4 | 2.0 | 0.15 | 4 |
| Stress | 100,000 | 6 | 3.0 | 0.20 | 6 |
- Build per-event ledgers for browse, cart, order, realtime and vector search.
- Compare (A) normalized reads, (B) denormalized order snapshots, (C) materialized dashboard counters, and (D) shorter session/event retention.
- For Standard, calculate document/index-entry operations. For Enterprise, calculate RU/WU/realtime units only from explicit byte assumptions or managed Query Explain measurements.
- Report best/base/worst monthly billable units and identify the top two sensitivity variables.
- Reject any architecture whose cheapest case violates security, latency, consistency or recovery acceptance criteria.
If doubling listener changes increases forecast cost more than doubling DAU, listener churn is the parameter to monitor. If vector scan entries dominate, query/index quality is the lever. The model should tell you what evidence matters next.
8. Controlled failure: choose “cheapest” using average user behavior
Inject a heavy-tail cohort: 2% of users refresh product search 50× more often than median. A mean-only forecast underestimates query and network cost. Repair by modeling percentiles/cohorts and an abuse/stress scenario. Product usage distributions are rarely uniform.
Production judgment: cost is one axis of the decision surface
A more expensive write-heavy model can be correct if it meets latency and consistency goals with predictable reads. A cheaper scan-heavy model can be fragile if growth makes p99 and RU explode. Use a multi-axis decision: correctness, p95/p99, throughput, billable units, operability, security, recovery and migration complexity.
Knowledge check
- Why is “cost per event” more useful than “cost per database” early in design?
- When is denormalization semantically correct rather than just faster?
- What determines materialized-vs-on-demand aggregate economics?
- Why is retention a cost and governance decision together?
- What is the value of sensitivity analysis?
Review the answers
1. It maps cost to product behavior and lets you scale/compare architecture choices before traffic exists.
2. When copied fields represent immutable historical facts/snapshots that should not follow source changes.
3. Query frequency and scan work versus source-event frequency and materialization writes/storage.
4. Deleting sooner reduces storage/scan/recovery footprint but may violate product, audit or legal requirements.
5. It identifies which uncertain variable dominates the result and therefore deserves monitoring/testing.
Summary and next step
This lesson established the working contract for Model Cost per User/Feature/Event and Compare Denormalization, Fan-Out, Aggregation, and Retention Alternatives. Keep its edition/mode assumptions, trust boundary, verification evidence, and operational constraints explicit when reusing the pattern.
Next, continue to Load-Test and Cost-Test a Feature Before Launch with Explicit Volume, Growth, and Worst-Case Assumptions.
Authoritative references
- Google Cloud: Firestore Standard edition pricing — location-specific document operations, storage, PITR, backups/restores and network pricing.
- Google Cloud: Firestore Enterprise edition pricing — Read Units, Write Units, realtime updates, storage, networking, Query Explain and recovery pricing.
- Firebase: Understand Cloud Firestore billing — index-entry reads, aggregations, listeners, offsets, Rules-dependent reads and free quota.
- Firebase: Firestore usage and limits — Standard free quota and current hard/configuration limits.
- Firebase: Enterprise Native mode quotas and limits — Enterprise free-tier units and limits.
- Firebase: Compare Standard and Enterprise Native mode — billing/index/realtime differences.
- Google Cloud Billing budgets — alert budgets notify; ordinary alert budgets do not automatically cap spend.