Twenty Years of the Machine Business
A single long-run view of the machine business built from three sources that had never been read together: the AFTEC timecard, the project register, and the invoice ledger. It answers four plain questions — how many hours, how many machines, how much revenue, and did prices really rise 260% — and in answering them surfaces two revenue streams that no project-based report can see.
Report: psi-analytics/eto/reports/twenty_year_machine_business.html
Builder: psi-analytics/eto/scripts/build_twenty_year_view.py (every figure computed at build
time; nothing on the page is typed in)
The three sources, and which question each answers
| Source | File | What only it can answer |
|---|---|---|
| Timecard | dgwreportfiles/tslabor2.csv | hours, by year and by department — including internal builds and Process Services |
| Project register | Project1287List.xml | machines shipped, order value at ship date, retrofit vs new build, internal vs customer |
| Invoice ledger | dgwreportfiles/invoiceline.csv | what was actually billed, and what it was billed for |
The project register and the invoice ledger are two different revenue measures and both are right. The register carries order value at ship date; the ledger carries invoiced value, which picks up progress billings, change orders, spare parts and Process Services work that never touch a project. Invoiced machine revenue averages $32.9M/yr against $27.4M/yr of project value at ship — the gap is the change orders and progress billings, not an error. State which measure a figure uses whenever you quote one.
Order-type classification (the key to the ledger)
invoiceline.csv carries Ord Type per line. The letters were established by reading sample lines,
not inferred from the code:
| Type | What it is | How it was confirmed |
|---|---|---|
U | pre-2021 catch-all for all project work | 45,113 of 45,284 lines carry part SPECIALS |
MC | machine contract, 2021+ | median line $74,809 |
MD | small machine / development, 2021+ | median $9,000 |
S | spare parts, in use since 1990 | real part numbers, median line $378 |
SV | field service | “Calibration Service”, “Shot Peen Machine Calibration” |
PS | Process Services (the job shop) | “Line 1 Powder”, Bloom Energy |
W | warranty replacements | median $100 |
Customer service = S + SV. Averaged 2006–2025: $5.1M/yr (parts $4.9M, field service
$0.2M), rising from $1.8M in 2006 to $12.1M in 2025 — now 27% of machine revenue and the
quietly compounding line while machine revenue stayed range-bound.
Two limits stated on the report itself. Field service only exists as its own order type from 2020; before that it was billed inside the parts or project types and cannot be separated, so early years understate customer service. And 2015 parts reads $0.7M against $4–5M either side, almost certainly a data gap rather than a collapse in parts sales. Not yet chased down.
New builds and retrofits are never added together
| Stream | Mean/yr | CV | Median YoY swing | Best ÷ worst year |
|---|---|---|---|---|
| New machines | $23.8M | 33.6% | 27.8% | 3.5× |
| Retrofits | $3.6M | 53.4% | 40.9% | 13.4× |
Retrofits are the more volatile stream, not the steadier one. An earlier draft of the report claimed retrofit revenue was “the ballast, not the growth” — measurement contradicted it on both halves. Retrofits swing harder on every metric above, and they are the faster-growing share: 8.7% of machine revenue in 2006–2010 rising to 16.8% in 2021–2025. The claim was removed.
Machine price inflation: the “260%” estimate is roughly right, at 2.52×
The naive comparison — median new-machine price, 1996–2000 against 2021–2025 — gives 2.59× ($305k → $790k, 174 vs 168 machines). That number is contaminated by mix, so it was decomposed:
| Component | Ratio | Meaning |
|---|---|---|
| Price per labour hour | 1.91× | $189/hr (late 1990s) → $361/hr (today) |
| Hours per machine | 1.24× | machines carry more work than they used to |
| Like-for-like, same families | 2.52× | 79% of machines covered by families present in both eras |
So the ~260% figure holds, but roughly a quarter of it is machines getting bigger, not prices going up. Family-level ratios range from 1.49× (Pressure Blast) to 3.08× (Plasma Spray) — quoting a single company-wide inflation number hides a 2× spread between product lines.
Ghost machines: the work no revenue figure can see
PSI builds equipment for its own plant — Building 4 lines, ARGO inspection automation, R&D rigs. Real engineering and shop hours go in; almost no order value is ever recorded.
| Measure | 2006–2026 |
|---|---|
| Hours on internal builds | 76,356 |
| Valued at the price per labour hour of the year worked | $25.7M |
| Average | ~$1.2M/yr, peak $3.8M (2022) |
| Internal builds | 96 (order value recorded on almost none) |
How they are dated. The same way a customer machine is: by ship date. Only 50 of the 73 numeric internal jobs carry one, so the rest fall back to the last year that took labour — the year the build finished, not the year it was busiest. (A peak-year rule was tried first and dumped 13 in-flight builds into 2026 while leaving 2025 empty.) A job still taking hours in the partial year has not finished, so it is counted as in-flight (13) and appears in no year. 60 builds are dated.
Ghost volume is layered into the revenue, machines-shipped and hours charts with hatched
shading — stacked to scale so its size is honest, visually marked out so it never reads as
revenue. Building 4 -Stk work contributes hours and value but is excluded from the machine
count, because it is a standing job rather than a discrete machine.
This is not money we lost. It answers what would we have invoiced had a customer bought this machine. The capacity may not have been sellable, and the machine earns its keep in the plant. Read it as the scale of work the revenue figures cannot see.
Process Services is not a side business
The report originally said the job shop was “shown for scale and excluded from everything else”. That framing was wrong and has been replaced.
| Measure | Process Services | Rest of company |
|---|---|---|
| 2026 run-rate (8 complete months, latest invoice 09/2026) | $45.8M | $51.5M |
| Invoiced in those 8 months | $30.6M | $34.3M |
| Growth since 2021 | +18.1%/yr | flat |
| Share of all clocked hours, 2006 → 2026 | 3% → 52% | 97% → 48% |
At 18.1% it passes the rest of the company in 2027 (~$54.2M projected). Process Services is still held out of every machine-business series on the page — its ~200,000 hours/yr would swamp any machine trend — but that is now framed as a comparability decision, not a size judgement, in the lede, the footer and its own section.
Why growth is measured from 2021 and not from the start. Before ~2020 Process Services work was
invoiced under the U catch-all, so early years understate it and some apparent growth is
reclassification. 2021 onward is clean. The hours series needs no such caveat — department 125
has been its own department throughout and shows the same rise. Two independent sources agreeing is
the reason to believe it.
Reading the charts
- Hatched segments are not revenue. A 45° hatch over a colour means the segment stacks to scale but is deliberately marked out (used only for ghost machines).
- Grouped charts are side by side, not stacked, and their tooltips omit the total — used where the sum of two series is not a meaningful quantity (Process Services against the rest of PSI).
- The last year is partial and marked with
*on every axis. Run-rates state how many complete months they use.
Known limitations
- Machine hours exclude department 125. Every machine-business hours figure is machine-build only; Process Services hours appear only in its own section.
- Order value at ship date is not revenue recognition. It is the register’s value on the ship date, which is neither the invoiced total nor the accounting revenue for that year.
- Ghost valuation uses the company-wide price per labour hour, not the family the internal machine belongs to, so an individual ghost build’s value is indicative rather than a quote.
- 2015 total revenue diverges −16.7% from
psi_quarterly_metrics.csv. Not reconciled. - Not in the nightly pipeline — manually triggered, so the report goes stale silently. Re-run before presenting; it stamps its own source vintage in the header.
Related
- Project-Charged Labor & the Business Central Container — where the hours in this report come from, and the
PROJpseudo work order - Weld Shop Utilization — the
dgwreportfilesexport map and whylabor_detailcan’t be used for this - Quarterly Business Metrics — same repo, shares
lib/psi_data.py - AFTEC Job Costing & WIP — how cost (not just hours) reaches a job
- Project1287 Data Patterns — read before writing anything against
PROJECT.1287 - Terminology — job number conventions (4-digit new build, ≥10000 retrofit)
Created: 2026-09-04
Source: psi-analytics/eto/scripts/build_twenty_year_view.py, templates/twenty_year_view.html