Founding as a Developer — Validate Before You Build
Measure the Interest on Debt from Deploy Records and Decide When to Pay
Goal
From the deployment and work records, calculate the DORA metrics and the interest per module (unplanned work hours), and decide "should we pay it off now" by the rule using the payback period, net savings, and cost of delay of the refactoring candidates.
Why it matters
Whether to pay off technical debt or ship features is usually decided by voices. If you put interest, principal, and the value of the features being postponed in the same unit, that argument becomes a calculation. Interest you have not measured looks like it does not exist, and one day it eats the time of the whole team.
Materials
/opt/fixtures/founder/debt/deploys.csv—deploy_id,service,committed_at,deployed_at,failed,recovered_at,unplanned(times are UTC, 12 weeks)/opt/fixtures/founder/debt/worklog.csv—week,module,planned_hours,unplanned_hours(weeks 1–12)/opt/fixtures/founder/debt/options.json—team_hours_per_week, hourly_cost_krw, horizon_weeks, refactor{모듈: {cost_hours, interest_reduction}}, feature{name, value_per_week_krw}(the Korean word in the code means module)
Definitions (names follow dora.dev)
- Deployment frequency = the service's number of deployments ÷ 12. Change lead time = deployed_at − committed_at (hours). Change fail rate = failed=1 ÷ total. Failed deployment recovery time = the median of recovered_at − deployed_at (hours) for failed=1 deployments. Deployment rework rate = unplanned=1 ÷ total.
- Interest = the module's unplanned_hours.
mean(12-week average),first4(average of weeks 1–4),last4(average of weeks 9–12). - Savings = last4 × interest_reduction. Payback period = cost_hours ÷ savings. Net savings over the horizon = (savings × horizon_weeks − cost_hours) × hourly_cost_krw. Cost of delay = cost_hours ÷ team_hours_per_week × value_per_week_krw.
- Decision: if the net savings of the candidate with the shortest payback period > the cost of delay, that module's name; otherwise
"feature_first". - Rounding: hours and weeks to two decimal places, rates to four, won to integers.
Steps
- In
/root/founder/debt/dora.py, createfrequency(fix, service)(deployments per week, a real number). - In
dora.py, addlead_time(fix, service)→{"median_h": x, "mean_h": y}. - In
dora.py, addchange_fail_rate(fix, service). - In
dora.py, addrecovery_median(fix, service)(hours). - In
/root/founder/debt/dora.json, writefrequency_per_week, lead_time_median_h, lead_time_mean_h, change_fail_rate, recovery_median_h, rework_ratefor each service. - In
/root/founder/debt/interest.json, writemean, first4, last4, rising(last4 > first4) for each module. - In
/root/founder/debt/plan.json, writesaved_per_week, payback_weeks, net_saved_krw, delay_cost_krwfor each refactoring candidate. - In
/root/founder/debt/decision.json, writedecision(the rule in the definitions),worst_service(the service with the highest change fail rate), andfastest_payback(the candidate with the shortest payback period).
Notes
statistics.median,statistics.mean,datetime.strptime(s, "%Y-%m-%dT%H:%M:%SZ")- Common mistakes: looking only at the mean of lead time, taking the denominator of the change fail rate as the number of incidents or days, computing recovery time as a mean, judging growing interest by the 12-week mean, and leaving out the cost of delay.
Deployment frequency
In /root/founder/debt/dora.py, create frequency(fix, service) — that service's number of deployments ÷ 12.
Divide the number of lines in deploys.csv filtered by service by 12 weeks.
Change lead time — median and mean
Add lead_time(fix, service) → {median_h, mean_h} to dora.py.
Convert each deployment's (deployed_at − committed_at) into hours, build a list, and use median and mean from statistics.
Change fail rate — the denominator is deployments
Add change_fail_rate(fix, service) to dora.py.
Divide the number of deployments that needed immediate intervention right after deployment (failed=1) by that service's total number of deployments.
Failed deployment recovery time
Add recovery_median(fix, service) to dora.py (failed deployments only, hours, median).
It is the median of (recovered_at − deployed_at) for deployments with failed=1. None if there are no failures.
One page of DORA per service
In /root/founder/debt/dora.json, write frequency_per_week, lead_time_median_h, lead_time_mean_h, change_fail_rate, recovery_median_h, and rework_rate for each service.
Deployment rework rate = unplanned=1 ÷ total deployments. Hours to two decimal places and rates to four.
Interest and trend by module
In /root/founder/debt/interest.json, write mean, first4, last4, and rising for each module.
Sort by week, then compute the average of the first 4 weeks and of the last 4 weeks separately.
Payback period, net savings, and cost of delay
In /root/founder/debt/plan.json, write saved_per_week, payback_weeks, net_saved_krw, and delay_cost_krw for each refactoring candidate.
Savings is the recent interest (last4) × interest_reduction. The cost of delay is the number of weeks the refactoring uses team time × the feature's weekly value.
Decide by the rule
In /root/founder/debt/decision.json, write decision, worst_service, and fastest_payback.
Look only at the candidate with the shortest payback period, and if its net savings exceed the cost of delay, the module name; otherwise feature_first.