A two-person platform team moved a summarization job onto a free model lane in spring. The savings looked obvious on the invoice they never printed. Six months later the lane changed shape, and the rewrite took nine working days.
That rewrite was the real price. Nobody put it in the spreadsheet.
This is a field guide for the opposite question. Most teams ask whether a free lane is good enough today. Fewer ask what it costs to leave. Below is a manifest format, a runnable calculator, and a decision table you can commit next to your service code.
Why the Sticker Price Wins the Argument
Free lanes are easy to adopt and expensive to abandon. Adopting costs an afternoon and a config change. Abandoning costs schemas, prompts, evals, glue code, and trust.
The asymmetry is the trap. A lane that saves a few hundred dollars a month still loses if the exit costs more than the horizon of savings.
Four Buckets of Exit Cost
Most estimates miss two of these. Track all four.
- Rewrite labor. Hours to replace the client, the retry logic, and the response parsing.
- Eval rebuild. Hours to re-baseline prompts, scoring, and golden sets against a new endpoint.
- Glue and schema rework. Tool-call formats, JSON modes, streaming frames, error taxonomies.
- Downtime and egress. The migration window plus any data movement charges.
Risk buffer belongs on top. Migrations overrun. A 25 percent buffer is a floor, not pessimism.
Commit a Lane Manifest
Keep the assumption file in the repo. Review it in the same pull request that adds the dependency.
{
"lane": {
"name": "free-model-lane-a",
"monthly_saving_usd": 1200,
"expected_months": 12
},
"exit_work": {
"rewrite_hours": 40,
"eval_rebuild_hours": 24,
"glue_rewrite_hours": 16,
"egress_gb": 20,
"downtime_hours": 4
},
"assumptions": {
"hourly_rate_usd": 85,
"risk_buffer_pct": 25
}
}
Each field is a claim you can defend in review. Guessed hours are still better than absent hours, because guesses get argued with.
A Calculator With No Dependencies
Standard library only. No network calls, no vendor SDKs, no login.
#!/usr/bin/env python3
"""exit_cost.py - price the departure before you accept the lane.
Usage:
python3 exit_cost.py lane.json
python3 exit_cost.py lane.json --ci # exit 1 when verdict is REJECT
"""
import json
import sys
DEFAULTS = {
"hourly_rate_usd": 85,
"egress_usd_per_gb": 0.09,
"downtime_usd_per_hour": 400,
"risk_buffer_pct": 25,
}
def _money(x):
return f"${x:,.0f}"
def evaluate(manifest):
a = {**DEFAULTS, **manifest.get("assumptions", {})}
w = manifest["exit_work"]
rate = a["hourly_rate_usd"]
buckets = {
"rewrite (model/API swap)": w["rewrite_hours"] * rate,
"eval rebuild": w["eval_rebuild_hours"] * rate,
"glue + schema rework": w["glue_rewrite_hours"] * rate,
"egress": w["egress_gb"] * a["egress_usd_per_gb"],
"downtime": w["downtime_hours"] * a["downtime_usd_per_hour"],
}
subtotal = sum(buckets.values())
total = subtotal * (1 + a["risk_buffer_pct"] / 100.0)
lane = manifest["lane"]
saving = lane["monthly_saving_usd"] * lane["expected_months"]
ratio = saving / total if total else 0.0
if ratio >= 1.0:
verdict = "ACCEPT"
elif ratio >= 0.6:
verdict = "ACCEPT-WITH-DRILL"
else:
verdict = "REJECT"
return buckets, subtotal, total, saving, ratio, verdict
def main(argv):
path = argv[1]
ci = "--ci" in argv
with open(path, encoding="utf-8") as fh:
manifest = json.load(fh)
buckets, subtotal, total, saving, ratio, verdict = evaluate(manifest)
print(f"lane: {manifest['lane']['name']}")
print("-" * 46)
for name, value in buckets.items():
print(f"{name:<28}{_money(value):>12}")
print("-" * 46)
print(f"{'subtotal':<28}{_money(subtotal):>12}")
print(f"{'with risk buffer':<28}{_money(total):>12}")
print(f"{'saving over horizon':<28}{_money(saving):>12}")
print(f"{'coverage ratio':<28}{ratio:>12.2f}")
print(f"verdict: {verdict}")
if ci and verdict == "REJECT":
return 1
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv))
Run it against the manifest above. Output is deterministic and diffable.
$ python3 exit_cost.py lane.json
lane: free-model-lane-a
----------------------------------------------
rewrite (model/API swap) $3,400
eval rebuild $2,040
glue + schema rework $1,360
egress $2
downtime $1,600
----------------------------------------------
subtotal $8,402
with risk buffer $10,502
saving over horizon $14,400
coverage ratio 1.37
verdict: ACCEPT
Drop monthly_saving_usd to 300 and the same exit work returns a ratio of 0.34 and a REJECT. The exit did not change. The horizon did.
Reading the Verdict
Three outcomes, three actions. Do not soften the middle one.
| Verdict | Coverage ratio | Action |
|---|---|---|
ACCEPT |
>= 1.00 | Ship, and re-run the calculator each quarter |
ACCEPT-WITH-DRILL |
0.60 - 0.99 | Ship behind a practiced rollback, not a theoretical one |
REJECT |
< 0.60 | Keep the paid lane, or shrink the workload first |
ACCEPT-WITH-DRILL is the honest middle. Plenty of lanes are worth it when the exit is rehearsed and not when it is improvised.
Signals That Push Toward REJECT
- The lane touches a signed webhook path or a money path.
- Prompts are hand-tuned with no golden set to re-baseline.
- The workload has no second client implementation.
- Migration downtime lands on a launch or a billing cycle.
Where a Free Lane Like MonkeyCode Fits
MonkeyCode is an open-source project offering free model access and a free server option. Treat both as one candidate lane in the manifest, not as a default.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
The free server option matters for this worksheet. It changes the deploy path too, so add a server_exit block to the manifest when you use it. Quotas, model availability, and terms change, so read the current project page before filling in the numbers. This article does not fix any of them.
A useful pattern from the account's earlier work: evaluate the lane, do not marry it. Score it, then run a drill.
python3 exit_cost.py lane.json --ci || echo "lane blocked: exit cost too high"
That line belongs in CI next to the dependency check, not in a wiki page.
Limitations and Who Should Skip This
- The calculator is arithmetic, not forecasting. Hours are still guesses.
- Shared assumptions hide disagreement. Argue the rate, not the total.
- Batch jobs with trivial clients often exit in hours. Skip the ceremony.
- Regulated data paths need a compliance review the script cannot model.
- Teams with no eval harness should fix that before pricing any lane.
If the workload has never failed in production, keep the numbers rough and revisit later. If it has, be pessimistic.
Exit Criteria in the README
Write the departure terms down while adoption still feels good. Four lines is enough.
- Re-run
exit_cost.pyon the first of every quarter. - Freeze new glue code against the lane once ratio drops below 0.60.
- Rehearse a rollback within one week of any terms change.
- Kill the lane if the coverage ratio stays below 0.40 for two quarters.
A lane is a lease, not a home. Price the move-out before you sign, and the deprecation notice becomes an expense you already budgeted. If you want to score a free lane this week, start with the project's current terms page, then run the calculator on your own numbers.
Top comments (0)