back-of-the-envelope

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Back-of-the-Envelope Estimation (BOTEC)

信封背面估算(BOTEC)

Turn vague scale ("high traffic", "huge data") into a few concrete numbers that decide the design. BOTECs are quick, approximate calculations — feasibility checks, not precision. The point is the process and directional correctness: they tell you when a single database won't do, when caching is forced, when a write spike needs a queue.
A design for 1k QPS and one for 1M QPS are different systems. 10 GB fits in RAM; 10 TB needs distributed storage. Estimate first, choose second.
将模糊的规模描述(如“高流量”“大数据”)转化为能决定设计方向的具体数字。BOTEC是快速的近似计算——用于可行性检查,而非追求精度。关键在于计算过程和方向正确性:它能告诉你何时单数据库不足以支撑需求、何时必须引入缓存、何时写入峰值需要队列来处理。
针对1k QPS和1M QPS的设计是完全不同的系统。10 GB数据可放入内存;10 TB数据则需要分布式存储。先估算,再选择方案。

When to reach for this

适用场景

At step 2 of any design (right after requirements), and any time a choice depends on scale: sizing the read vs write path, deciding sharding vs a single node, justifying a cache, or sanity-checking a proposed component against load.
在任何设计的第2步(紧随需求梳理之后),以及任何选择取决于规模的场景:读写路径规模规划、决定分片还是单节点部署、论证缓存的必要性,或者根据负载合理性检查拟选组件。

When NOT to

不适用场景

Don't chase precision or model every microservice — that's the opposite of the technique. Don't estimate what won't change a decision (YAGNI). Round aggressively: "99,987 / 9.1" is "100,000 / 10". Always label units and write assumptions down.
不要追求精度或为每个微服务建模——这与该技术的核心相悖。不要估算那些不会改变决策的内容(YAGNI原则)。大胆取整:“99,987 / 9.1”应简化为“100,000 / 10”。始终标注单位写下假设条件

Clarify first

先明确前提

Estimates are only as good as their inputs. Pin down:
  • DAU/MAU and what fraction is active daily.
  • Actions per user per day (posts, reads, messages…).
  • Read:write ratio — which path dominates.
  • Object sizes — per record and per media blob.
  • Retention — how long data is kept (drives total storage).
  • Peak factor — peak is typically ~2× average; spikier for some workloads.
估算的质量取决于输入信息的准确性。需明确以下几点:
  • 日活跃用户数(DAU)/月活跃用户数(MAU) 以及每日活跃用户的占比。
  • 每位用户每日操作数(如发帖、阅读、消息发送等)。
  • 读写比例——哪条路径占主导地位。
  • 对象大小——每条记录和每个媒体 blob的大小。
  • 数据留存周期——数据保留时长(决定总存储需求)。
  • 峰值系数——峰值通常约为平均值的2倍;某些负载的峰值波动会更大。

The core estimations (recipes)

核心估算公式

Work each as a single multiply/divide chain. Full worked numbers and the CPU-time derivation are in
references/estimation-recipes.md
.
  • QPS =
    DAU × actions_per_user_per_day ÷ 86,400
    . Peak QPS ≈ 2 × QPS (state your peak factor).
  • Storage/day =
    writes_per_day × avg_object_size
    . Total =
    storage/day × retention_days
    (watch base-10 vs base-2; storage is sold base-10).
  • Bandwidth =
    QPS × payload_size
    (separate read and write; egress usually dominates and costs money).
  • Number of servers =
    peak_QPS ÷ per_server_QPS
    . Use the per-server rates below as the divisor.
  • Concurrent connections / memory =
    concurrent_users × per_connection_cost
    ; check the working set fits RAM (else it's an IO-bound, disk-backed design).
每个估算都可通过单一乘除链完成。完整的计算示例和CPU时间推导见
references/estimation-recipes.md
  • QPS =
    DAU × 每位用户每日操作数 ÷ 86,400
    峰值QPS ≈ 2 × QPS(需说明你使用的峰值系数)。
  • 每日存储需求 =
    每日写入数 × 平均对象大小
    总存储需求 =
    每日存储需求 × 留存天数
    (注意十进制与二进制的区别;存储产品通常按十进制计量)。
  • 带宽 =
    QPS × 负载大小
    (需区分读和写;通常出口带宽占主导且产生成本)。
  • 服务器数量 =
    峰值QPS ÷ 单服务器QPS
    。使用下方的单服务器处理速率作为除数。
  • 并发连接数/内存 =
    并发用户数 × 单连接成本
    ;检查工作集是否能放入内存(否则将成为IO密集型、基于磁盘的设计)。

Numbers that matter

关键参考数值

These are the reference points to know, so you can estimate without lookups. Full tables (latency, server specs, request types, powers of two, nines) live in
references/numbers-to-remember.md
— load it when you need a specific figure.
The two that drive most decisions:
WhatRule of thumb
Single SQL/RDBMS node~1,000 QPS
Key-value store node~10,000 QPS
Cache server (Redis/Memcached)~100,000–1M QPS
One modern CPU core~1,000 simple requests/s → a 64-core box ≈ 64k req/s
Read 1 MB: memory vs SSD vs disk~μs vs tens–hundreds of μs vs ms (memory ≫ SSD ≫ disk)
Think in orders of magnitude, not exact values. CPU-bound work is ~1×, memory-bound ~10×, IO-bound ~100× the time. That ratio, not the decimals, is what shifts an architecture.
这些是需要牢记的参考点,以便无需查阅资料即可完成估算。完整的表格(延迟、服务器规格、请求类型、2的幂、可用性等级)存于
references/numbers-to-remember.md
——需要具体数值时可查看该文档。
驱动大多数决策的两个核心参考:
类别经验法则
单节点SQL/RDBMS~1000 QPS
键值存储节点~10000 QPS
缓存服务器(Redis/Memcached)~100000–1000000 QPS
单颗现代CPU核心~1000 次简单请求/秒 → 一台64核服务器 ≈ 64000 次请求/秒
读取1MB数据:内存 vs SSD vs 磁盘~微秒 vs 几十到几百微秒 vs 毫秒(内存 ≫ SSD ≫ 磁盘)
以数量级思考,而非精确数值。 CPU密集型工作耗时约为1×,内存密集型约为10×,IO密集型约为100×。这个比例,而非小数位,才是影响架构选择的关键。

Dos and don'ts

注意事项

Distilled from the recipes and the ways estimates mislead.
Do
  • Do round to one significant figure and reason in orders of magnitude — the ratio (1× / 10× / 100×) is what shifts an architecture, not the decimals.
  • Do size on peak, not average. State the peak multiplier (≈2× is a common default; spikier for bursty workloads) before picking capacity.
  • Do estimate reads and writes separately — a 95% read ratio and a write spike pull the design in opposite directions.
  • Do label units and write assumptions down, so a "GB" isn't ambiguous and the chain can be re-checked when an input changes.
Don't
  • Don't carry false precision. Decimals imply a confidence the inputs don't support; "99,987" is "100,000".
  • Don't trust per-server rates as universal. "1k QPS for SQL" is a point-query rule of thumb; range scans, joins, and fat payloads can be 10× worse — use it for the order of magnitude, then validate with real benchmarks.
  • Don't conflate base-2 and base-10. RAM is base-2; storage/network marketing is base-10 — close enough for an estimate, but only if the units are stated.
  • Don't compute what won't change the decision. If a number doesn't move the architecture, skip it (YAGNI).
从估算公式和常见估算误区中提炼而来。
应当
  • 应当保留一位有效数字并以数量级为单位推理——比例(1× / 10× / 100×)才是影响架构的关键,而非小数位。
  • 应当按峰值而非平均值规划规模。在选择容量前说明峰值乘数(默认约为2×;突发型负载的峰值乘数会更高)。
  • 应当分别估算读和写——95%的读比例和写入峰值会将设计推向完全不同的方向。
  • 应当标注单位并写下假设条件,避免“GB”含义模糊,且当输入信息变更时可重新检查计算链。
不应当
  • 不应当保留虚假精度。小数位意味着输入信息无法支撑的置信度;“99,987”应简化为“100,000”。
  • 不应当将单服务器速率视为通用标准。“SQL单节点1k QPS”是点查询的经验法则;范围扫描、关联查询和大负载的性能可能差10倍——用它来判断数量级,之后再通过真实基准测试验证。
  • 不应当混淆二进制与十进制。内存按二进制计量;存储/网络产品宣传通常按十进制计量——估算时可以近似,但必须明确单位。
  • 不应当计算那些不会改变决策的内容。如果某个数值不会影响架构选择,就跳过它(YAGNI原则)。

Diagram

图示

Estimation is usually a table, not a picture — keep the numbers and assumptions inline. When a derived number forces a structural change (e.g. "300k QPS > single DB → shard / add replicas"), that belongs in the architecture diagram itself; use the
architecture-diagram
skill when drawing the design those numbers justify.
估算通常以表格形式呈现,而非图片——将数值和假设条件内嵌即可。当推导的数值迫使架构发生变化时(例如“300k QPS > 单数据库处理能力 → 分片/添加副本”),该变化应体现在架构图中;绘制这些数值所支撑的设计时,请使用
architecture-diagram
技能。

Related building blocks

相关组件

  • requirements-scoping
    depends on it for the inputs (DAU, action rates, ratios, SLAs) this skill turns into numbers.
  • data-storage
    feeds into it: the storage totals and shard counts computed here drive its SQL/NoSQL and partitioning choices.
  • caching
    feeds into it: a high read ratio or hot working set sized here is the case for a cache.
  • scaling-evolution
    feeds into it: when an estimate crosses a per-node ceiling, that ceiling is the next bottleneck to plan around.
  • system-design
    owned-concept lives here for the reasoning loop; this is the orchestrator that calls this skill at step 2.
  • requirements-scoping
    — 依赖该技能获取输入信息(DAU、操作速率、比例、SLA),本技能将这些信息转化为数值。
  • data-storage
    — 本技能的输出会影响该组件:计算得出的存储总量和分片数量会驱动SQL/NoSQL的选择以及分区策略。
  • caching
    — 本技能的输出会影响该组件:此处计算出的高读比例或热工作集规模是引入缓存的依据。
  • scaling-evolution
    — 本技能的输出会影响该组件:当估算值超过单节点上限时,该上限就是下一个需要规划解决的瓶颈。
  • system-design
    — 该技能包含此估算的核心逻辑;它是在第2步调用本技能的协调器。

References

参考资料

  • references/numbers-to-remember.md
    — the cheat sheet: latency table, typical server spec, per-server QPS rates, CPU/memory/IO-bound request types, powers of two, availability nines. Read when you need a specific figure.
  • references/estimation-recipes.md
    — worked examples (Twitter-scale QPS + storage, the 64-core→64k req/s CPU-time derivation, bandwidth and server-count sizing). Read to see a full chain end to end.
  • references/numbers-to-remember.md
    — 速查表:延迟表、典型服务器规格、单服务器QPS速率、CPU/内存/IO密集型请求类型、2的幂、可用性等级。需要具体数值时可阅读。
  • references/estimation-recipes.md
    — 完整示例(Twitter规模的QPS+存储计算、64核→64k请求/秒的CPU时间推导、带宽和服务器数量规划)。阅读以了解完整的计算链。

Scripts

脚本

For a deterministic check of a sizing chain (the one place exact arithmetic earns its keep), run the calculator rather than doing it by hand:
  • scripts/botec.py
    python3 scripts/botec.py --dau 150e6 --actions 2 --peak 2 --obj-bytes 1e6 --media-frac 0.10 --retention-days 1825 --server-qps 1000 --json
    → QPS, peak, storage/day & total, bandwidth, server count. Per-server-QPS defaults mirror the rules of thumb above (override with
    --server-qps
    ).
  • scripts/test_botec.py
    — asserts the calculator matches
    expected_outputs/twitter_scale.json
    (the worked Twitter example), so the prose recipe and the math can't drift.
如需确定性地检查规模计算链(唯一需要精确计算的场景),请运行计算器而非手动计算:
  • scripts/botec.py
    python3 scripts/botec.py --dau 150e6 --actions 2 --peak 2 --obj-bytes 1e6 --media-frac 0.10 --retention-days 1825 --server-qps 1000 --json
    → 输出QPS、峰值QPS、每日存储需求&总存储需求、带宽、服务器数量。单服务器QPS默认值与上述经验法则一致(可通过
    --server-qps
    参数覆盖)。
  • scripts/test_botec.py
    — 验证计算器输出是否与
    expected_outputs/twitter_scale.json
    (Twitter规模的示例)匹配,确保文字描述的公式与实际计算逻辑一致。