平台團隊如何用四項維護負擔測試評估免費 AI 方案
Should Your Platform Team Take the Free AI Tier? Use This 4-Part Ops-Absorption Test
作者提出四部分維護負擔測試,讓平台團隊在採用免費 AI 方案前,先比較每週維護工時與成本取捨。測試以一週任務紀錄計算每項被接受變更的 token 用量,並比較免費託管、付費 API 與自託管,同時檢查維護人手、資料限制及退出成本。
Two posts sat near the top of DEV in the same week, and they were arguing with each other.
"One Weekend: 3,000 Open-Source AI Projects" (2026-10-11) said the supply of free AI tooling is now effectively infinite. "AI Fatigue? Yea I know." (2026-10-13) said the appetite for running any of it is not.
Both can be true. That is exactly the trap for a platform team. Free options multiply, and every one of them asks for the same thing you are shortest on: someone's attention.
So here is the question I want you to answer before you accept any free tier. Not "is the model good?" Not "is the price zero?" But: how many ops hours per week does this lane quietly charge you?
Below is the test I use, a script to measure the one number that drives it, and a worked example with real arithmetic. All numbers are labeled where they are modeled rather than measured. A scorecard like this is a conversation tool, not objective truth.
The decision is not "free vs paid". It is three lanes
Most teams compare two things and miss the third.
| Lane | Cash cost | Ops hours | Hard ceiling |
|---|---|---|---|
| A. Free hosted tier | ~0 | ~0 | Token or rate allowance, set by the vendor |
| B. Paid hosted API | Per 1M tokens | ~0 | Budget only |
| C. Self-hosted model server | Hardware + power, amortized | Yours, weekly, forever | Your patience and your on-call |
Lane A and Lane B share a property that Lane C does not: nobody has to get paged. That property is the thing you are actually pricing.
And Lane A has a second property people forget — a ceiling that is not measured in dollars. You cannot buy your way past it with a budget approval. You buy past it with a migration.
Define five variables before you compare anything
Write these on one line and put them in the doc. Undefined variables are how free-tier decisions get made by vibes.
- N — engineers using the assistant.
- T — tokens per engineer-week, including retries and rejected attempts. Measured, not estimated.
- R — your blended hosted price per 1M tokens, from your actual contract.
- S — monthly amortized cost of the self-hosted box (hardware over its useful life, plus power and rack).
- C — loaded engineer-hour cost. Use your real number; it is usually higher than the one people quote in meetings.
Then two derived numbers:
- Hosted monthly =
N × T × 4.33 ÷ 1,000,000 × R - Break-even ops hours per week =
(hosted monthly − S) ÷ (4.33 × C)
That second formula is the whole article. It tells you how many hours of your team's week the self-hosted lane may consume before it stops being the cheaper option. If the answer is smaller than the hours you already know you'll spend, the decision is made.
The one number to measure first: tokens per accepted change
Here is what I keep seeing. Teams measure token spend per request. That number is useless for this decision, because requests are not the unit anyone cares about.
The unit is the accepted change: a diff that merged and was not reverted within seven days.
Why the seven-day revert window? Because a change that gets rolled back next Tuesday consumed tokens and produced nothing. Counting it as output flatters every lane, and flatters the free one most, since free tokens make failed attempts feel costless.
So log this CSV for one week. Columns: engineer,task,prompt_tokens,completion_tokens,accepted,rework_minutes.
#!/usr/bin/env python3
"""token_shape.py -- measure token shape, then price two lanes.
Input CSV: engineer,task,prompt_tokens,completion_tokens,accepted,rework_minutes
accepted = 1 when the change merged and was not reverted within 7 days.
Usage:
python3 token_shape.py tasks.csv
python3 token_shape.py tasks.csv --team 8 --price 3.00 --server 600 --hour 95 --ops 4
"""
import argparse
import csv
MONTHS = 4.33 # average weeks per month
def load(path):
rows = []
with open(path, newline="", encoding="utf-8") as f:
for row in csv.DictReader(f):
rows.append({
"tokens": int(row["prompt_tokens"]) + int(row["completion_tokens"]),
"accepted": row["accepted"].strip() == "1",
"rework": float(row["rework_minutes"]),
})
return rows
def shape(rows):
accepted = [r for r in rows if r["accepted"]]
n_acc = max(len(accepted), 1)
total = sum(r["tokens"] for r in rows)
return {
"tasks": len(rows),
"accepted": len(accepted),
"tokens_per_accepted_change": total / n_acc,
"rework_min_per_accepted_change": sum(r["rework"] for r in accepted) / n_acc,
}
def lanes(team, tokens_week_per_eng, price_per_mtok, server_month, loaded_hour, ops_hours_week):
hosted = team * tokens_week_per_eng * MONTHS / 1_000_000 * price_per_mtok
owned = ops_hours_week * MONTHS * loaded_hour + server_month
breakeven_ops = (hosted - server_month) / (MONTHS * loaded_hour)
return hosted, owned, breakeven_ops
def main():
ap = argparse.ArgumentParser()
ap.add_argument("csv")
ap.add_argument("--team", type=int, default=8)
ap.add_argument("--price", type=float, default=3.00)
ap.add_argument("--server", type=float, default=600.0)
ap.add_argument("--hour", type=float, default=95.0)
ap.add_argument("--ops", type=float, default=4.0)
ap.add_argument("--changes-per-eng-week", type=float, default=6.0)
ap.add_argument("--allowance", type=float, default=10_000_000)
args = ap.parse_args()
s = shape(load(args.csv))
per_acc = s["tokens_per_accepted_change"]
print(f"tasks={s['tasks']} accepted={s['accepted']}")
print(f"tokens_per_accepted_change={per_acc:,.0f}")
print(f"rework_min_per_accepted_change={s['rework_min_per_accepted_change']:.1f}")
print(f"allowance_covers_accepted_changes={args.allowance / per_acc:,.0f}")
tokens_week = per_acc * args.changes_per_eng_week
hosted, owned, breakeven = lanes(
args.team, tokens_week, args.price, args.server, args.hour, args.ops
)
print(f"hosted_month=${hosted:,.0f}")
print(f"self_hosted_month=${owned:,.0f}")
print(f"breakeven_ops_hours_per_week={breakeven:.2f}")
if __name__ == "__main__":
main()
Run it. Then look at tokens_per_accepted_change. That single number decides whether you are in a light shape or a heavy one, and those two shapes lead to completely different conclusions about the same nominal free allowance.
Worked example: same allowance, two very different worlds
Here is the arithmetic I get asked to do most often, done out loud. Assume an operator-supplied free allowance of up to 10,000,000 tokens (the figure given to me for this piece, verify it in-product before you rely on it).
| Shape | Tokens per accepted change | Accepted changes the allowance covers |
|---|---|---|
| Context-light edit loop | ~165,000 | ~60 |
| Context-heavy agent loop (large repo, retries) | ~1,900,000 | ~5 |
Same allowance. One is a usable month for a small team. The other is a measurement budget.
That is not a knock on the free tier. It is a statement about your workload. If you don't know which row you are in, you don't know what you were offered, and neither does the person who approved it.
The lane comparison, filled in
Modeled example, not measured. N = 8, heavy shape at 6 accepted changes per engineer-week → T ≈ 11.4M tokens/engineer-week. R = $3.00/1M. S = $600/month. C = $95/hour.
- Hosted monthly = 8 × 11.4M × 4.33 ÷ 1M × $3 ≈ $1,185
- Self-hosted at 4 ops h/week = 4 × 4.33 × $95 + $600 ≈ $2,245
- Break-even ops hours = (1,185 − 600) ÷ (4.33 × 95) ≈ 1.4 h/week
Read that last line again. Self-hosting this workload wins on cash only if your team spends under roughly ninety minutes a week keeping the box alive. Not during migration. Every week, including the week after a driver upgrade.
Sensitivity: where the line moves
Ops hour sensitivity, holding everything else fixed:
| Ops h/week | Self-hosted $/mo | Hosted $/mo |
|---|---|---|
| 1 | $1,011 | $1,185 |
| 2 | $1,423 | $1,185 |
| 3 | $1,834 | $1,185 |
| 4 | $2,245 | $1,185 |
| 6 | $3,068 | $1,185 |
Price sensitivity at H = 4:
| R ($/1M) | Hosted $/mo | Break-even ops h/week |
|---|---|---|
| $1 | $395 | never (negative) |
| $3 | $1,185 | 1.4 |
| $8 | $3,159 | 6.2 |
| $15 | $5,924 | 12.9 |
Notice the direction. Cheaper hosted tokens make self-hosting harder to justify, not easier. That is the opposite of the intuition that sends teams shopping for GPUs.
One incident, priced
An afternoon outage with 8 engineers, 6 hours, 30% blocked: 8 × 6 × 0.3 × 95 ≈ $1,368. That single afternoon is larger than the monthly hosted premium. Two such afternoons a year and the "free" server has cost more than the API line item — before you count the roadmap you didn't ship.
The 4-part gate, with hard stops
Run these in order. A fail is a stop, not a discussion.
Gate 1 — Shape. Do you know tokens_per_accepted_change from at least one week of logged tasks? No measurement, no decision. Stop.
Gate 2 — Ops budget. Is there a named owner with H hours blocked on a calendar, every week, not borrowed from feature work? "We'll find the time" is a fail. Stop.
Gate 3 — Data boundary. Can your code leave the environment at all? If any repo in scope is under a contractual or regulatory restriction, the free hosted lane and the paid hosted lane are both out. Stop.
Gate 4 — Exit cost. What does leaving cost, in engineer-days, including the prompt and config work you'll rebuild? Write the number down before you start. If it is unknown, it is unbounded.
Owner: the platform lead, named. Expiry: 90 days from the first logged task — re-run the script and re-derive. Exit criteria, written up front: ops hours exceed break-even for three consecutive weeks; or acceptance rate drops below your recorded baseline; or exit cost exceeds the savings you projected.
Where a free hosted lane genuinely earns a place
Not in production. In measurement.
Gate 1 is the cheap gate and the one teams skip. Standing up a self-hosted box to measure your token shape is backwards — you buy the expensive lane to answer a question the cheap lane answers in a week.
This is the honest case for something like MonkeyCode, an open-source AI coding project whose operator offers free model access (up to 10,000,000 tokens as described to me on 2026-10-18) and a free server option. As of that date, both are availability claims to verify in-product, not a contract. Use them for Gate 1: a week of real tasks, real rework minutes, real revert counts, no procurement.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
What you get out of that week is not a demo. It's the per_acc number that tells you whether your light shape covers 60 accepted changes or your heavy shape covers 5 — and whether Lane C is even worth pricing.
Who should not use this approach
- Teams with a hard latency or residency requirement. Hosted lanes of any kind, free or paid, are out. Run Gate 3 and move on.
- Teams without a named owner. You will not log a week of data. Buy the paid hosted lane and revisit in two quarters.
- Anyone who needs pinned model versions for reproducibility. Free tiers change under you. Your evals will drift and you'll blame the model.
- Teams treating the free server as a place to keep the only copy of anything. It is a measurement sandbox. Mean it.
- Anyone who thinks this scorecard produces a verdict. It produces the numbers that make the meeting short.
The question that actually reverses this
Don't ask whether the free tier is worth trying. Almost always, yes — for one week, for Gate 1.
Ask instead: what is the highest H your team would still accept for owning the box? Get that number from your manager before you run the script. If the honest answer is "zero" and your break-even comes back at 1.4, you were never making a cost decision. You were making a staffing decision wearing a spreadsheet.
Write down per_acc, the break-even hours, the owner, and the expiry date. Then, in ninety days, ask which of those four moved first.
來源:DEV Community · dev.to