本地优先的系统设计容量模拟器 · 離線系統設計容量模擬器 · Local-first System Design Capacity Simulator
排队论解析模型 × 离散事件仿真双引擎,在写第一行部署代码前,先把系统「压到崩」看清楚瓶颈在哪。
🔁 双引擎交叉验证:Erlang-C / M/M/c/K 闭式解析(毫秒级出结果)+ 纯标准库离散事件仿真(验证解析结论),全程离线、零第三方依赖。
ScaleForge(容量锻造台) 是一款面向后端工程师、SRE 与准备系统设计面试的开发者的离线容量规划与瓶颈推演工具。你用一份 JSON 描述系统拓扑(网关、服务、缓存、数据库、消息队列、Worker),它就能回答四个灵魂问题:
- 当前流量下,端到端 p50/p95/p99 延迟是多少?错误率多少?
- 第一个被压垮的组件是谁?调用链上的瓶颈路径是什么?
- 流量继续上涨,系统在哪个 RPS 断裂?离 SLO 击穿还有多少余量?
- 要扛住目标流量,每个组件至少需要扩到几个实例?一个月大概花多少钱?
- 系统设计材料大多是静态架构图和「加缓存、上队列」的经验口诀,缺少对排队行为的量化直觉:为什么利用率一过 70%,p99 就开始非线性飙升?
- 真实压测要先把系统写出来、部署起来,成本高、周期长,还可能打挂共享环境;
- 纸上算容量只会用「QPS ÷ 单机 QPS」,忽略排队等待、扇出调用、缓存穿透、超时重试放大,结果上线即雪崩。
- 🧮 双引擎互验:闭式排队模型(Erlang-C、有限队列 M/M/c/K、Allen-Cunneen 通用近似、Little 定律、尾延迟反解)与独立实现的离散事件仿真互为校验,数字不是「画出来好看」的。
- 🧾 Scenario-as-Code:一份 JSON 即可版本化、进 Git、进 CI;支持
--strict在 SLO 击穿时以非零退出码拦截变更。 - 🧗 负载扫描与断裂点检测:自动扫描 RPS 区间,分别给出利用率上限、p99 SLO 上限、错误率上限,取最严约束作为安全水位。
- 🩺 瓶颈根因链 + 扩容反解:定位入口到瓶颈的调用路径,并反解每个组件满足目标利用率所需的最少并发数/副本数。
- 🌩️ 故障机制建模:有限队列丢弃、超时 + 有限次重试的负载放大效应(被放弃的请求仍在下游占用算力——这正是重试风暴的机理)、缓存命中率吸收、同步/异步扇出。
- 📉 四种报告形态:彩色终端报告 + ASCII 趋势图、机器可读 JSON、Markdown、单文件离线 HTML 报告(手写 SVG 图表,无任何外部资产)。
- 📦 零依赖、跨平台、单文件:Python 3.8+ 标准库即可运行;一条命令打成
scaleforge.pyz单文件随身带。
项目受近期 GitHub 热门的分布式系统教学模拟器启发(画布式拖拽、拉高流量观察排队行为)。我们认同「用实验代替口诀」的理念,但选择了一条不同的路:CLI / 代码优先、可复现、可进 CI、解析与仿真互验、直接产出容量规划结论,并补充了画布产品不具备的 SLO 水位计算、扩容反解与成本估算。未使用其任何代码或素材,全部实现为独立自研。
| 模块 | 能力 |
|---|---|
| 🧮 解析引擎 | M/M/1、M/M/c(Erlang-C 等待概率)、M/M/c/K 有限队列丢弃率、Allen-Cunneen 非指数服务近似、p50/p95/p99 尾延迟闭式反解 |
| 🎲 离散事件仿真 | 自写事件循环:泊松到达、指数/定长/Gamma 服务时间、多服务台、有界 FIFO 队列、超时计时器、有限重试、同步/并行扇出、缓存吸收,固定随机种子可复现 |
| 🕸️ 拓扑流量传播 | DAG 调用图、按边扇出倍数、缓存穿透率、重试放大定点迭代收敛、并行取 max / 串行求和的延迟合成 |
- 📈 负载扫描(Sweep):线性抬升 RPS,输出 p99 / 利用率 / 错误率 / 有效吞吐曲线,自动标注安全水位与余量百分比。
- 🩺 诊断与建议:过载、高利用率、队列溢出、超时风险、重试放大、缓存机会等分级发现项(critical / warning / ok),每条都附带可执行建议。
- 💰 成本估算:内置通用实例目录(参考价,可覆盖),估算月度成本与每百万请求成本。
- 🖥️ 终端体验:ANSI 彩色表格、ASCII 折线图与迷你趋势线,
--no-color适配管道与 CI。 - 🧰 库友好:每个引擎都是纯函数式 API,可直接嵌入你自己的自动化容量评审流水线。
- 🔒 隐私安全:不发起任何网络请求、不收集遥测,场景数据永不出本机;无正则注入、无动态执行,JSON 仅做结构解析。
- Python 3.8 及以上(Windows / macOS / Linux 均可),无需安装任何第三方依赖。
git clone https://github.com/gitstq/ScaleForge.git
cd ScaleForge
# 跑一遍内置示例:解析 + 仿真交叉验证 + 负载扫描
python3 -m scaleforge analyze examples/02_cache_async.json --sim --sweep --no-colorpython3 -m scaleforge init my-system.json # 写入一份带注释结构的示例
python3 -m scaleforge check my-system.json # 先校验拓扑与字段
python3 -m scaleforge analyze my-system.jsonbash scripts/build_pyz.sh # Windows 用 scripts/build_pyz.ps1
python3 dist/scaleforge.pyz --version
python3 dist/scaleforge.pyz analyze examples/01_monolith.jsonpip install .
scaleforge analyze examples/03_retry_storm.json --rps 60最快的一次完整体验:
# 把一个「超时 90ms + 重试 2 次」的系统从 60 rps 加压到 140 rps,看重试风暴
python3 -m scaleforge analyze examples/03_retry_storm.json --rps 60 --no-color
python3 -m scaleforge analyze examples/03_retry_storm.json --rps 140 --sweep --no-color{
"name": "my-service",
"description": "一句话描述",
"entrypoint": "gateway",
"rps": 120.0,
"slo": { "p99_ms": 400.0, "max_error_rate": 0.001, "max_utilization": 0.7 },
"components": [
{ "name": "gateway", "kind": "gateway", "replicas": 2, "concurrency": 8,
"service_time_ms": 3.0, "instance_type": "standard" }
],
"edges": [
{ "source": "gateway", "target": "orders", "calls": 1, "mode": "parallel" }
]
}组件字段说明:
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
name |
string | 必填 | 组件唯一名 |
kind |
string | service | gateway/service/cache/database/queue/worker/external |
replicas |
int | 1 | 副本数 |
concurrency |
int | 1 | 单副本并发服务台数;总服务台 = 副本 × 并发 |
service_time_ms |
float | 0 | 单次调用平均处理耗时;0 表示纯透传节点(如逻辑队列) |
service_cv |
float | 1.0 | 服务时间变异系数:0=定长,1=指数分布,其余按 Gamma |
max_queue |
int | -1 | 等待队列长度,-1 无界;满了即丢弃 |
cache_hit |
float | 0.0 | 本节点就地吸收、不再调用下游的比例(如缓存命中率) |
timeout_ms |
float | 0 | 调用方对该组件的超时;>0 时启用超时概率计算 |
retries |
int | 0 | 超时/丢弃后的重试次数(重试策略声明在被调方) |
instance_type |
string | 自动 | 成本目录中的实例型号 |
边字段: calls(每个父请求产生的调用次数,支持小数表示概率调用)、mode(sequential 串行延迟求和 / parallel 并行取最大)。
| 命令 | 作用 | 常用参数 |
|---|---|---|
init [path] |
生成示例场景 | --force 覆盖 |
check <file> |
仅校验场景 | — |
analyze <file> |
稳态解析 + 诊断 + 成本 | --rps 覆盖流量;--sim 加仿真;--sweep 加扫描;--strict CI 门禁;--format text/json/md/html;--out 写文件 |
simulate <file> |
只跑离散事件仿真 | --duration 60 --warmup 5 --seed 42 |
sweep <file> |
只做负载扫描 | --min-rps --max-rps --steps |
场景 A:容量评审(给目标流量,反推资源)
python3 -m scaleforge analyze design.json --rps 500 --format md --out review.md报告的 Capacity plan 直接给出每个组件「当前服务台 → 所需服务台 → 副本数建议 → 剩余承载余量」。
场景 B:CI 容量门禁(架构改动导致 SLO 击穿即失败)
python3 -m scaleforge analyze design.json --rps 300 --strict
# SLO 满足退出码 0;击穿退出码 3,可直接挂在流水线里场景 C:离线 HTML 报告(发给评审会)
python3 -m scaleforge analyze examples/02_cache_async.json --sim --sweep \
--format html --out report.html样例报告见 docs/sample-report.html(浏览器直接打开,无需联网),拓扑示意见 docs/topology.svg。
场景 D:当 Python 库嵌入
from scaleforge.model import Scenario
from scaleforge.engine import analyze
from scaleforge.sweep import sweep
from scaleforge.diagnose import diagnose
scn = Scenario.load("design.json")
result = analyze(scn, rps=300)
print(result.e2e_p99_ms, result.goodput_rps, result.bottleneck)
plan = diagnose(scn, result)
for item in plan.capacity_plan:
print(item.component, item.required_servers, item.recommended_replicas)
curve = sweep(scn, 50, 800, steps=30)
print("安全水位 RPS:", curve.safe_rps)- util(利用率):到达率 ÷ 总服务率。长期 ≥100% 队列无界增长;超过 SLO 设定的
max_utilization(默认 70%)即给出排队预警。 - p99:端到端第 99 百分位延迟,沿关键路径合成(解析值,仿真报告给出独立测量值对照)。
- drop:有界队列溢出比例;retry:重试造成的下游负载倍数。
- safe load:扫描中同时满足利用率、p99、错误率三条 SLO 的最大 RPS。
Offered load : 140.00 rps Goodput: 0.00 rps Errors: 100.0% [SLO BREACHED]
component kind in rps srv util wait ms p99 ms drop retry
db database 420.00 8 100.0% ∞ ∞ 65.4% 3.00x
✗ CRIT [db] Arrival 420.0 rps >= service capacity 145.5 rps (rho -> 100%)
⚠ WARN [db] Retries multiply downstream load by x3.00.
同一个系统在 60 rps 时 SLO 全绿,140 rps 时因「慢库 + 90ms 超时 + 2 次重试」把下游放大 3 倍后整体崩塌——这就是重试风暴,ScaleForge 在部署前就能把它算出来。 (运行录屏/GIF 占位:
docs/demo.gif)
- 解析引擎和仿真结果应该完全一致吗? 均值在低/中负载下应高度一致;尾延迟受仿真时长与随机种子影响会有统计波动,可加大
--duration收敛。解析模型用于快速扫描,仿真用于最终验证。 - 支持网络调用真实压测吗? 不支持,也刻意不做——ScaleForge 是离线建模工具,不发任何网络包;真实压测请配合 k6 / wrk / Locust。
- 服务时间怎么测? 用线上 P50 均值作为
service_time_ms,用 P50/P99 估算变异系数service_cv;不确定时保持默认 1.0(指数分布是保守上界)。
闭式公式(Erlang-C 家族)毫秒级、可对整个流量区间做扫描,但依赖分布假设;离散事件仿真不依赖闭式假设、能刻画超时/重试这类动态过程,但每次运行有统计成本。ScaleForge 让两者共存:用解析引擎做扫描与规划,用仿真引擎做交叉验证,并且两套实现完全独立,避免同一个错误互相背书。
- 纯标准库 Python:容量计算是轻量数学问题,零依赖意味着任何机器、任何 CI、任何离线环境都能直接跑;
heapq足以承载事件驱动仿真。 - JSON 而非自定义 DSL:零学习成本、天然可 diff、可被任何语言生成。
- 手写 SVG 报告:HTML 报告不依赖 CDN/图表库,离线可开、可邮件转发、永不因为外链失效而白屏。
- v1.1:熔断器(open / half-closed / closed)状态机进入仿真引擎
- v1.2:漏桶/令牌桶限流与自适应扩缩容(HPA 风格)策略仿真
- v1.3:场景对比 diff(改副本数前后两份报告自动对照)
- v1.4:更多排队模型(M/G/c/k 精确数值解、优先级队列)
- v1.5:从 OpenTelemetry / Prometheus 指标草稿自动生成场景文件
社区贡献方向:新组件类型、新实例价格目录、教学场景库(经典故障模式复现)、报告主题。
ScaleForge 属于脚本 / 工具库类项目,无需安装常驻服务。
# Linux / macOS
bash scripts/build_pyz.sh
# Windows PowerShell
powershell -ExecutionPolicy Bypass -File scripts/build_pyz.ps1
# 产物 dist/scaleforge.pyz,任何装有 Python 3.8+ 的机器:python3 scaleforge.pyz ...python3 -m pip wheel . --no-deps -w dist # 产出 py3-none-any 通用 wheel
pip install dist/scaleforge-1.0.0-py3-none-any.whl- uses: actions/setup-python@v5
with: { python-version: "3.11" }
- run: python3 -m unittest discover -s tests
- run: python3 -m scaleforge analyze design.json --rps 300 --strict兼容环境:Python 3.8 / 3.9 / 3.10 / 3.11 / 3.12,操作系统无关;内存占用 < 50MB,单次分析为毫秒级,60 秒仿真为亚秒级。
欢迎 Issue 与 PR!请先阅读 CONTRIBUTING.md。提交信息遵循 Angular 规范:feat: / fix: / docs: / test: / refactor:。核心约束:运行时零第三方依赖、所有解析结论必须有已知值测试或仿真对照、仿真必须可被种子复现。
基于 MIT License 开源,可自由商用、修改与分发,保留版权声明即可。内置实例价格仅为参考估算,请以云厂商官网实时报价为准。
🔁 雙引擎交叉驗證:Erlang-C / M/M/c/K 閉式解析(毫秒級出結果)+ 純標準函式庫離散事件模擬(驗證解析結論),全程離線、零第三方相依套件。
ScaleForge(容量鍛造台) 是一款為後端工程師、SRE 與準備系統設計面試的開發者打造的離線容量規劃與瓶頸推演工具。你用一份 JSON 描述系統拓撲(閘道、服務、快取、資料庫、訊息佇列、Worker),它就能回答四個關鍵問題:
- 目前流量下,端到端 p50/p95/p99 延遲是多少?錯誤率多少?
- 第一個被壓垮的元件是誰?呼叫鏈上的瓶頸路徑是什麼?
- 流量持續上升,系統會在哪個 RPS 斷裂?距離 SLO 擊穿還剩多少餘裕?
- 要撐住目標流量,每個元件至少要擴到幾個副本?一個月大概要多少預算?
- 系統設計教材多半是靜態架構圖與「加快取、上佇列」的口訣,缺乏對排隊行為的量化直覺:為什麼利用率一過 70%,p99 就開始非線性暴衝?
- 真實壓測得先把系統寫完、部署上線,成本高、週期長,還可能打掛共用環境;
- 紙上算容量只會「QPS ÷ 單機 QPS」,忽略排隊等待、扇出呼叫、快取穿透、逾時重試放大,結果上線即雪崩。
- 🧮 雙引擎互驗:閉式排隊模型(Erlang-C、有限佇列 M/M/c/K、Allen-Cunneen 通用近似、Little 定律、尾延遲反解)與獨立實作的離散事件模擬互為校驗,數字絕非「畫得好看」。
- 🧾 Scenario-as-Code:一份 JSON 即可版控、進 Git、進 CI;
--strict可在 SLO 擊穿時以非零結束碼攔截變更。 - 🧗 負載掃描與斷裂點偵測:自動掃描 RPS 區間,分別給出利用率上限、p99 SLO 上限、錯誤率上限,取最嚴約束做為安全水位。
- 🩺 瓶頸根因鏈 + 擴容反解:定位入口到瓶頸的呼叫路徑,並反解各元件達成目標利用率所需的最少服務台/副本數。
- 🌩️ 故障機制建模:有限佇列丟棄、逾時 + 有限次重試的負載放大效應(被放棄的請求仍會在下游佔用運算——這正是重試風暴的機制)、快取命中率吸收、同步/非同步扇出。
- 📉 四種報告形態:彩色終端機報告 + ASCII 趨勢圖、機器可讀 JSON、Markdown、單檔離線 HTML 報告(手寫 SVG 圖表,完全無外部資產)。
- 📦 零相依、跨平台、單檔案:Python 3.8+ 標準函式庫即可執行;一鍵打包成
scaleforge.pyz隨身攜帶。
專案受近期 GitHub 熱門的分散式系統教學模擬器啟發(畫布式拖曳、拉高流量觀察排隊行為)。我們認同「以實驗取代口訣」的理念,但選擇了不同路線:CLI/程式碼優先、可重現、可進 CI、解析與模擬互驗、直接產出容量規劃結論,並補上畫布產品欠缺的 SLO 水位計算、擴容反解與成本估算。未使用其任何程式碼或素材,全部為獨立自研。
- 🧮 解析引擎:M/M/1、M/M/c(Erlang-C 等待機率)、M/M/c/K 有限佇列丟棄率、Allen-Cunneen 非指數服務近似、Little 定律、p50/p95/p99 尾延遲閉式反解。
- 🎲 離散事件模擬:自寫事件迴圈:卜瓦松到達、指數/定長/Gamma 服務時間、多服務台、有界 FIFO 佇列、逾時計時器、有限重試、串行/並行扇出、快取吸收,固定隨機種子可重現。
- 🕸️ 拓撲流量傳播:DAG 呼叫圖、依邊扇出倍數、快取穿透率、重試放大定點迭代收斂、並行取 max/串行求和的延遲合成。
- 📈 負載掃描(Sweep):線性抬升 RPS,輸出 p99/利用率/錯誤率/有效吞吐曲線,自動標註安全水位與餘裕百分比。
- 🩺 診斷與建議:過載、高利用率、佇列溢出、逾時風險、重試放大、快取機會等分級發現(critical / warning / ok),每條都附可執行建議。
- 💰 成本估算:內建通用執行個體目錄(參考價,可覆寫),估算月度成本與每百萬請求成本。
- 🖥️ 終端體驗:ANSI 彩色表格、ASCII 折線圖與迷你趨勢線,
--no-color適應管線與 CI。 - 🧰 函式庫友善:每個引擎都是純函式 API,可直接嵌入自動化容量評審流水線。
- 🔒 隱私安全:不發起任何網路請求、無遙測,場景資料永不離開本機;JSON 僅做結構解析,無動態執行。
- Python 3.8 以上(Windows / macOS / Linux 皆可),無需安裝任何第三方套件。
git clone https://github.com/gitstq/ScaleForge.git
cd ScaleForge
python3 -m scaleforge analyze examples/02_cache_async.json --sim --sweep --no-colorpython3 -m scaleforge init my-system.json
python3 -m scaleforge check my-system.json
python3 -m scaleforge analyze my-system.jsonbash scripts/build_pyz.sh # Windows 請用 scripts/build_pyz.ps1
python3 dist/scaleforge.pyz analyze examples/01_monolith.jsonpip install .
scaleforge analyze examples/03_retry_storm.json --rps 60{
"name": "my-service",
"entrypoint": "gateway",
"rps": 120.0,
"slo": { "p99_ms": 400.0, "max_error_rate": 0.001, "max_utilization": 0.7 },
"components": [
{ "name": "gateway", "kind": "gateway", "replicas": 2,
"concurrency": 8, "service_time_ms": 3.0 }
],
"edges": [
{ "source": "gateway", "target": "orders", "calls": 1, "mode": "parallel" }
]
}元件欄位:kind(閘道/服務/快取/資料庫/佇列/Worker/外部服務)、replicas × concurrency=總服務台數、service_time_ms 平均處理時間(0 為純透傳節點)、service_cv 服務時間變異係數(0 定長、1 指數)、max_queue 有界佇列(-1 無界)、cache_hit 就地吸收比例、timeout_ms/retries 逾時與重試原則(宣告於被調端)。邊欄位:calls 扇出倍數(可為小數機率呼叫)、mode 為 sequential(延遲求和)或 parallel(取最大值)。
| 指令 | 用途 | 常用參數 |
|---|---|---|
init [path] |
產生範例場景 | --force 覆寫 |
check <file> |
校驗場景 | — |
analyze <file> |
穩態解析+診斷+成本 | --rps、--sim、--sweep、--strict、--format text/json/md/html、--out |
simulate <file> |
只跑離散事件模擬 | --duration 60 --warmup 5 --seed 42 |
sweep <file> |
只做負載掃描 | --min-rps --max-rps --steps |
# A. 容量評審:給目標流量反推資源,輸出 Markdown
python3 -m scaleforge analyze design.json --rps 500 --format md --out review.md
# B. CI 容量門禁:SLO 擊穿即傳回非零結束碼
python3 -m scaleforge analyze design.json --rps 300 --strict
# C. 離線 HTML 報告(範例:docs/sample-report.html,瀏覽器直接開)
python3 -m scaleforge analyze examples/02_cache_async.json --sim --sweep \
--format html --out report.htmlfrom scaleforge.model import Scenario
from scaleforge.engine import analyze
from scaleforge.sweep import sweep
from scaleforge.diagnose import diagnose
scn = Scenario.load("design.json")
result = analyze(scn, rps=300)
print(result.e2e_p99_ms, result.goodput_rps, result.bottleneck)
for item in diagnose(scn, result).capacity_plan:
print(item.component, item.required_servers, item.recommended_replicas)
print("安全水位 RPS:", sweep(scn, 50, 800, steps=30).safe_rps)util 為到達率 ÷ 總服務率,長期 ≥100% 佇列無界成長;p99 為沿關鍵路徑合成的第 99 百分位延遲;drop 為有界佇列溢出比例;retry 為重試造成的下游負載倍數;safe load 為同時滿足三條 SLO 的最大 RPS。
- 解析與模擬會完全一致嗎? 中低負載下均值應高度一致;尾延遲受模擬時長與種子影響有統計波動,可加大
--duration收斂。解析負責掃描,模擬負責驗證。 - 會真的發壓測流量嗎? 刻意不會,ScaleForge 是離線建模工具,不發任何網路封包;真實壓測請搭配 k6/wrk/Locust。
- 服務時間怎麼估? 取線上 P50 均值當
service_time_ms,服務時間分布越不穩定,service_cv越大;不確定就維持 1.0(指數分布為保守上界)。
閉式公式毫秒級、適合對整段流量區間掃描,但帶有分布假設;離散事件模擬不依賴閉式假設、能刻畫逾時/重試的動態過程,但有統計成本。ScaleForge 讓兩者共存:解析引擎做掃描與規劃,模擬引擎做交叉驗證,且兩套實作完全獨立,避免同一個錯誤互相背書。
- 純標準函式庫 Python:容量計算是輕量數學問題,零相依代表任何機器、任何 CI、任何離線環境都能直接執行,
heapq足以驅動事件模擬。 - JSON 而非自訂 DSL:零學習成本、原生可 diff、可被任何語言產生。
- 手寫 SVG 報告:不依賴 CDN 與圖表套件,離線可開、可郵件轉發,不因外連失效而白屏。
- v1.1:熔斷器(open / half-closed / closed)狀態機進入模擬引擎
- v1.2:漏桶/權杖桶限流與 HPA 風格自動擴縮容模擬
- v1.3:場景前後對照 diff(改副本數前後兩份報告自動比對)
- v1.4:更多排隊模型(M/G/c/k 精確數值解、優先權佇列)
- v1.5:從 OpenTelemetry/Prometheus 指標自動產生場景草稿
社群貢獻方向:新元件類型、各雲執行個體價格目錄、教學場景庫(經典故障模式復現)、報告主題。
本專案屬於腳本/工具函式庫類型,無常駐服務。
# 跨平台單檔案(Linux / macOS)
bash scripts/build_pyz.sh
# Windows PowerShell
powershell -ExecutionPolicy Bypass -File scripts/build_pyz.ps1
# 通用 wheel
python3 -m pip wheel . --no-deps -w dist相容環境:Python 3.8–3.12,作業系統無關;記憶體占用 < 50MB,單次分析毫秒級、60 秒模擬為亞秒級。CI 中可執行 python3 -m unittest discover -s tests 後以 analyze --strict 作為容量門禁。
歡迎 Issue 與 PR,請先參閱 CONTRIBUTING.md。提交訊息遵循 Angular 規範:feat:/fix:/docs:/test:/refactor:。核心原則:執行階段零第三方相依、所有解析結論必須有已知值測試或模擬對照、模擬必須能以種子重現。
以 MIT License 開源,可自由商用、修改與散布,保留版權聲明即可。內建執行個體價格僅供參考估算,請以雲端供應商官網即時報價為準。
🔁 Two independent engines cross-check each other: closed-form queueing analytics (Erlang-C / M/M/c/K, instant) and a standard-library-only discrete-event simulation. Fully offline, zero third-party dependencies.
ScaleForge is a local-first capacity planning and bottleneck reasoning tool for backend engineers, SREs and system-design interview prep. Describe your topology in one JSON file — gateways, services, caches, databases, queues, workers — and it answers four questions that usually require a running production-grade load test:
- At the current load, what are the end-to-end p50/p95/p99 latencies and error rate?
- Which component breaks first, and what is the call path that leads to it?
- As traffic keeps growing, at which RPS does the system violate its SLOs, and how much headroom remains?
- To serve a target load, how many replicas does every component actually need — and what does that cost per month?
- Most system-design material is static diagrams plus rules of thumb ("add a cache", "use a queue"). There is no quantitative intuition for why p99 turns nonlinear once utilization passes ~70%.
- Real load tests require building and deploying the system first — slow, expensive, and risky for shared environments.
- Back-of-the-envelope math ("QPS ÷ per-node QPS") ignores queueing wait, fan-out, cache penetration and timeout-retry amplification — so the design collapses on launch.
- 🧮 Dual engines, cross-validated. Closed-form models (Erlang-C, bounded M/M/c/K, Allen-Cunneen approximation, Little's law, inverse tail percentiles) and an independently written discrete-event simulator validate each other — no number is "animated to look plausible".
- 🧾 Scenario-as-Code. One JSON file you can version, diff and gate in CI;
--strictexits non-zero when an SLO is breached. - 🧗 Load sweeps & breaking-point detection. Ramp RPS automatically and derive three independent caps (utilization, p99, error rate); the strictest one becomes the safe load.
- 🩺 Bottleneck root-cause chain & inverse sizing. Trace the entrypoint-to-bottleneck path and solve backwards for the minimum servers/replicas that meet your utilization target.
- 🌩️ Failure mechanics. Bounded-queue drops, timeout + bounded-retry load amplification (abandoned calls keep consuming downstream capacity — the retry-storm mechanism), cache absorption, sequential/parallel fan-out.
- 📉 Four report formats. Color terminal tables with ASCII charts, machine-readable JSON, Markdown, and a single-file offline HTML report with hand-written SVG charts — no external assets at all.
- 📦 Zero dependencies, cross-platform, single-file. Python 3.8+ standard library only; build a portable
scaleforge.pyzwith one command.
ScaleForge was inspired by a recently trending interactive canvas simulator for teaching distributed-system behavior. We share the "run the experiment instead of memorizing rules" philosophy, but take a different path: CLI/code-first, reproducible, CI-friendly, with analytic/simulation cross-validation and direct capacity-planning outputs — SLO safe-load computation, inverse sizing and cost estimation that canvas products do not provide. No upstream code or assets were used; this is an independent implementation.
- 🧮 Analytic engine — M/M/1, M/M/c (Erlang-C wait probability), M/M/c/K bounded-queue blocking, Allen-Cunneen general-service approximation, Little's law, closed-form p50/p95/p99 inversion.
- 🎲 Discrete-event simulation — custom event loop with Poisson arrivals, exponential/constant/Gamma service times, multi-server pools, bounded FIFO queues, timeout timers, bounded retries, sequential/parallel fan-out and cache absorption; fully reproducible via
--seed. - 🕸️ Topology propagation — DAG call graph, per-edge fan-out, cache pass-through, fixed-point convergence of retry amplification, latency composition with parallel-max / sequential-sum semantics.
- 📈 Sweeps — linear RPS ramps producing p99 / utilization / error / goodput curves with annotated safe load and headroom.
- 🩺 Diagnosis — severity-ranked findings (overload, high utilization, queue overflow, timeout risk, retry amplification, cache opportunity), each with an actionable suggestion.
- 💰 Cost estimation — built-in reference instance catalog (overridable) for monthly cost and cost-per-million-requests.
- 🖥️ Terminal UX — ANSI tables, ASCII line charts and sparklines;
--no-colorfor pipes and CI. - 🧰 Library-friendly — every engine is a plain functional API you can embed in automated capacity reviews.
- 🔒 Privacy & safety — no network calls, no telemetry, scenarios never leave your machine; JSON is parsed structurally with no dynamic execution.
- Python 3.8+ on Windows / macOS / Linux. No third-party packages required.
git clone https://github.com/gitstq/ScaleForge.git
cd ScaleForge
python3 -m scaleforge analyze examples/02_cache_async.json --sim --sweep --no-colorpython3 -m scaleforge init my-system.json
python3 -m scaleforge check my-system.json
python3 -m scaleforge analyze my-system.jsonbash scripts/build_pyz.sh # Windows: scripts/build_pyz.ps1
python3 dist/scaleforge.pyz analyze examples/01_monolith.jsonpip install .
scaleforge analyze examples/03_retry_storm.json --rps 60A 30-second tour — watch a slow database plus a 90 ms timeout and 2 retries collapse under load:
python3 -m scaleforge analyze examples/03_retry_storm.json --rps 60 --no-color
python3 -m scaleforge analyze examples/03_retry_storm.json --rps 140 --sweep --no-color{
"name": "my-service",
"entrypoint": "gateway",
"rps": 120.0,
"slo": { "p99_ms": 400.0, "max_error_rate": 0.001, "max_utilization": 0.7 },
"components": [
{ "name": "gateway", "kind": "gateway", "replicas": 2, "concurrency": 8,
"service_time_ms": 3.0, "instance_type": "standard" }
],
"edges": [
{ "source": "gateway", "target": "orders", "calls": 1, "mode": "parallel" }
]
}Component fields:
| Field | Default | Meaning |
|---|---|---|
name |
required | unique component name |
kind |
service | gateway / service / cache / database / queue / worker / external |
replicas |
1 | replica count |
concurrency |
1 | servers per replica; total servers = replicas × concurrency |
service_time_ms |
0 | mean per-call service time; 0 = pass-through node (e.g. logical queue) |
service_cv |
1.0 | coefficient of variation: 0 constant, 1 exponential, otherwise Gamma |
max_queue |
-1 | waiting-room size; -1 unbounded, arrivals are dropped when full |
cache_hit |
0.0 | fraction absorbed locally without calling downstream |
timeout_ms |
0 | caller timeout; enables timeout-probability modeling when > 0 |
retries |
0 | retry attempts on timeout/drop (policy declared on the callee) |
instance_type |
auto | catalog entry used for cost estimation |
Edge fields: calls (downstream calls per parent call; decimals model probabilistic calls), mode (sequential sums latency, parallel takes the max).
| Command | Purpose | Key options |
|---|---|---|
init [path] |
write an example scenario | --force |
check <file> |
validate a scenario | — |
analyze <file> |
steady-state analysis + diagnosis + cost | --rps, --sim, --sweep, --strict, --format text/json/md/html, --out |
simulate <file> |
discrete-event simulation only | --duration 60 --warmup 5 --seed 42 |
sweep <file> |
load sweep only | --min-rps --max-rps --steps |
# A. Capacity review: target load -> resource plan as Markdown
python3 -m scaleforge analyze design.json --rps 500 --format md --out review.md
# B. CI gate: non-zero exit (3) when SLOs are breached
python3 -m scaleforge analyze design.json --rps 300 --strict
# C. Offline HTML report (see docs/sample-report.html for a rendered example)
python3 -m scaleforge analyze examples/02_cache_async.json --sim --sweep \
--format html --out report.htmlfrom scaleforge.model import Scenario
from scaleforge.engine import analyze
from scaleforge.sweep import sweep
from scaleforge.diagnose import diagnose
scn = Scenario.load("design.json")
result = analyze(scn, rps=300)
print(result.e2e_p99_ms, result.goodput_rps, result.bottleneck)
for item in diagnose(scn, result).capacity_plan:
print(item.component, item.required_servers, item.recommended_replicas)
print("safe rps:", sweep(scn, 50, 800, steps=30).safe_rps)- util = arrival rate ÷ total service rate. ≥100% means unbounded queue growth; above your
max_utilizationSLO (default 70%) you get a queueing warning. - p99 = end-to-end 99th-percentile latency composed along the critical path; the simulation report provides an independent measured counterpart.
- drop = bounded-queue overflow fraction; retry = downstream load multiplier caused by retries.
- safe load = largest RPS that simultaneously satisfies utilization, p99 and error SLOs.
Offered load : 140.00 rps Goodput: 0.00 rps Errors: 100.0% [SLO BREACHED]
db database 420.00 in rps 8 servers util 100.0% drop 65.4% retry 3.00x
✗ CRIT Arrival 420.0 rps >= service capacity 145.5 rps (rho -> 100%)
⚠ WARN Retries multiply downstream load by x3.00.
The same design is fully healthy at 60 rps but collapses at 140 rps because a slow database, a 90 ms timeout and 2 retries triple the downstream load — a textbook retry storm, visible before you deploy anything.
- Should analytics match the simulation exactly? Means match closely at low/medium load; tail percentiles carry statistical noise that shrinks with a longer
--duration. Use analytics for sweeps, simulation for final validation. - Does it send real load? Deliberately not — ScaleForge is an offline modeler and never opens a socket. Pair it with k6 / wrk / Locust for real traffic.
- How do I estimate service time? Use the production mean as
service_time_msand raiseservice_cvfor erratic latency; when unsure keep 1.0 (the exponential distribution is the conservative bound).
Closed-form math is instant and ideal for sweeps but assumes distributions. Discrete-event simulation needs no closed form and captures dynamic behavior like timeouts/retries, at a statistical cost. ScaleForge keeps both: analytics for planning sweeps, simulation for verification, implemented independently so one cannot vouch for the other's bug.
- Standard-library Python only. Capacity math is lightweight; zero dependencies means it runs on any machine, any CI, fully offline —
heapqis all the event loop needs. - JSON instead of a custom DSL. No learning curve, diff-friendly, generatable from any language.
- Hand-written SVG reports. No CDN or chart library: reports open offline, forward by email, and never white-screen on a dead external link.
- v1.1 — circuit breaker state machine (open / half-closed / closed) in the simulator
- v1.2 — leaky-bucket/token-bucket rate limiting and HPA-style autoscaling
- v1.3 — scenario diff (before/after replica-change comparison)
- v1.4 — richer queueing models (exact M/G/c/k numerics, priority queues)
- v1.5 — draft scenarios from OpenTelemetry / Prometheus metrics
Contribution areas: new component kinds, cloud price catalogs, a teaching-scenario library of classic failure modes, report themes.
ScaleForge is a script / library project — no long-running service.
# Cross-platform single-file app
bash scripts/build_pyz.sh # Linux / macOS
powershell -ExecutionPolicy Bypass -File scripts/build_pyz.ps1 # Windows
# Universal wheel
python3 -m pip wheel . --no-deps -w distCompatibility: Python 3.8–3.12, OS-independent; < 50 MB RAM, millisecond analysis and sub-second 60 s simulations. In CI, run python3 -m unittest discover -s tests, then gate with analyze --strict.
Issues and PRs are welcome — please read CONTRIBUTING.md first. Follow Angular-style commits (feat: / fix: / docs: / test: / refactor:). Hard rules: zero runtime dependencies, every analytic result needs a known-value or DES cross-check test, simulations must be seed-reproducible.
Released under the MIT License — free for commercial use, modification and redistribution with the copyright notice retained. Built-in instance prices are rough references; always verify against current vendor pricing.