The Hidden Costs That Never Make It Into an Estimate
Why this matters
A shop can have accurate task hours on every code it tracks and still lose ground on every job, because the estimate covers wrench time and the week contains far more than wrench time. The gap does not announce itself. It shows up as a P&L that never quite matches what job-level margins predicted, and as an owner who cannot explain why a shop full of profitable jobs is not a profitable shop.
The failure is not that these costs are unknown. Every owner can list them. The failure is that they are never measured, so they are never converted into a number an estimate can carry. This article is about the measurement, because a list of hidden costs you cannot quantify changes nothing about your next bid.
The test that finds all of it at once
Take one representative week. Add up every paid field hour. Then add up every hour that landed on a job code that week. Subtract.
That difference is your total hidden labor, and it is the single most informative number in this whole subject, because it is complete by construction. You do not have to think of every category. Anything you forgot is already inside the gap.
Run it on a normal week, not your best one and not your worst. Then run it again a quarter later, because one week is a sample of one and the gap moves with season and mix.
Where the hours actually go
| Gap | Why it hides | How to measure it |
|---|---|---|
| Travel between stops | Feels like it is inside the job, is usually coded to neither job | Separate travel code, or route data by day |
| Load-out and unload | Happens before and after the first and last job of the day | Fixed per tech per day; measure once, apply |
| Supplier counter and pickup runs | Feels like part of the job, rarely coded | Its own code; also count the trips |
| Waiting on access, decisions, other trades | Reads as slow work in the record | A waiting code, with a reason field |
| Closeout, photos, paperwork | Done at day end, in the truck, uncoded | Fixed per tech per day, sampled |
| Callbacks and warranty returns | Coded to the original job or to nothing | Callback rate multiplied by median callback hours |
| Diagnosis on jobs that never sell | Job never opens, so hours have nowhere to go | Unsold-estimate code, plus a count |
The last row is the one shops discover latest and it can be large. Every site visit that produces an estimate the customer declines consumed real hours. If you do not code them, your sold jobs quietly carry them without your knowing by how much.
Converting the gap into a load factor
A load factor is the multiplier that turns job-coded hours into paid hours. If 1.0 coded hour consumes 1.35 paid hours, your load factor is 1.35x and every estimate built on coded hours is short by 35 percent of its labor unless the factor is applied somewhere.
Compute it as paid field hours divided by job-coded hours over the measured period. Not the other way around, and check yourself here: the recovery percentage (coded divided by paid) and the load factor (paid divided by coded) are two different numbers describing the same thing, and confusing them is common. A 75 percent recovery is a 1.33x load factor, not a 1.25x one.
The rule that keeps a load factor honest
A load factor covers irreducible overhead. It must never absorb fixable waste.
The moment you factor in 3.5 hours a week of avoidable supplier counter time, you have priced that waste into every bid permanently, made yourself less competitive, and removed the pressure that would have fixed it. The correct sequence is measure, then remove what is removable, then factor the residual.
So the gap gets split into two piles before anything is factored. Irreducible: load-out, closeout, a realistic floor of travel, an honest callback reserve. Attackable: counter runs that a will-call or staging change eliminates, waiting caused by your own dispatch, second trips for parts that should have been on the list.
Attack the second pile for a quarter, then re-measure and factor what remains.
Worked example: reconciling one week
The week. Two field techs, 40.0 paid hours each, so 80.0 paid field hours total.
Job-coded hours that week: 58.0.
The gap: 80.0 minus 58.0 is 22.0 hours, which is 27.5 percent of the 80.0 paid hours. Put the other way, 58.0 of 80.0 paid hours landed on a job code, a recovery of 72.5 percent.
The load factor as measured: 80.0 paid divided by 58.0 coded is 1.38x. Every job-coded hour is really consuming about 1.38 paid hours.
Decomposing the 22.0 hours. The shop turns on the standing codes described above for two weeks and gets a breakdown:
- Travel between stops, not previously coded: 9.0 hours
- Load-out and unload: 5.0 hours (0.5 hours per tech per day, 2 techs, 5 days)
- Supplier counter and pickup runs: 3.5 hours
- Waiting on access and customer decisions: 2.5 hours
- Closeout, photos, and paperwork: 2.0 hours (0.2 hours per tech per day, 2 techs, 5 days)
Those five sum to 22.0 hours, which reconciles to the gap.
Sorting into irreducible and attackable. Load-out at 5.0 and closeout at 2.0 are structural, so 7.0 hours are irreducible as the shop currently runs. Travel at 9.0 hours across two techs over five days is about 0.9 hours per tech per day, which is not obviously wasteful but is partly a routing question, so it splits: treat it as irreducible for now and put routing on the improvement list. Supplier runs at 3.5 and waiting at 2.5 are the attackable pile, 6.0 hours, about 7.5 percent of the 80.0 paid hours.
The improvement. Over the next quarter the shop moves to phoning orders ahead for counter pickup and adds an access-confirmation call the day before. Re-measured, supplier runs drop to 1.5 hours and waiting to 1.0, so the attackable pile falls from 6.0 hours to 2.5.
Re-computing. The gap is now 22.0 minus 3.5 recovered, so 18.5 hours. If that recovered time is filled with job work rather than simply absorbed, coded hours rise to 61.5 and the load factor becomes 80.0 divided by 61.5, which is 1.30x. If the time is not filled, the load factor does not move at all, and that condition matters: recovering hours only pays if there is work to put in them.
What gets applied to estimates. A 1.30x load factor on job-coded hours, not the 1.38x originally measured. Applying 1.38x would have baked 3.5 hours a week of now-fixed waste into every bid the shop writes.
Sanity check on the arithmetic. The original 1.38x means a 4.0-hour coded task consumes about 5.5 paid hours. At 1.30x it consumes 5.2. On a job type running roughly 4.0 coded hours, the difference between factoring honestly and factoring lazily is about 0.3 paid hours per job, which across a few hundred jobs a year is not a rounding error.
Measuring the two hardest ones
Callback and warranty reserve. Measure the callback rate as a share of jobs and the median callback hours, then multiply. Illustrative: if callbacks land on 6 percent of jobs and the median callback takes 1.5 hours, the reserve is 0.06 times 1.5, which is 0.09 hours per job. On a job type carrying 4.0 coded hours, that is about 2 percent added. Small, and worth carrying explicitly, because the moment your callback rate doubles the reserve doubles with it and you will see the change in your pricing rather than only in your margin.
Track the reserve against actual callback hours consumed each quarter. If actual keeps exceeding reserve, the issue is quality or scoping, not pricing, and raising the reserve is treating a symptom.
Unsold estimate time. Count the site visits that produced estimates which did not sell, and the hours in them. Divide by the number of jobs that did sell, and you have the hours per sold job that your winning work has to carry. A shop closing 1 estimate in 3 carries the diagnosis time of two dead visits on every live one, and that is worth knowing before deciding whether free estimates on a given job type make sense.
The non-labor gaps
Consumables. Blades, fasteners, tape, sealant, small fittings. Rarely listed, always used. Measure by dividing total consumable purchases over a quarter by field hours in that quarter, giving a consumable rate per field hour that can ride on the estimate as a line rather than a rounding error.
Disposal and haul-away. Easy to forget on job types where it is occasional. Count how often it actually occurs on a job type, and if the frequency is high enough, carry it on every bid of that type at its frequency rather than remembering it sometimes.
Rental idle time. Rentals are billed by elapsed time, not by hours used. A unit picked up Friday for a Monday job carries a weekend. Measure by comparing rental days billed against rental days used across a quarter.
Payment acceptance. Card and financing acceptance carries a percentage of the ticket. It is small per transaction and completely invisible if it is never allocated to job cost. Allocate it at the observed rate on the share of tickets paid that way.
Where the load factor must not go
Do not bury the factor inside task hours. If a 4.0-hour task becomes a 5.2-hour task in the template, three things break: the next person to measure that task will find a 4.0-hour actual and "correct" the template back down, you can no longer compare your task hours to any external reference, and you lose the ability to see the factor change.
Carry it as its own visible line. Templates hold clean task hours; the estimate applies the factor on top. That separation is what lets you improve either one without corrupting the other.
What changes the answer
Highly variable travel. A shop with a dense urban route and a shop covering a wide rural territory cannot share a load factor. If your travel per job varies by more than roughly a factor of two across your service area, estimate travel per job from the actual distance rather than folding it into a blanket factor.
Install-heavy versus service-heavy mix. Long install days recover a much higher share of paid hours than a day of short service calls, because the fixed per-day and per-stop overheads are spread over more coded hours. Compute separate factors by work type or the blended figure will overprice installs and underprice service calls.
A shop where the owner still runs calls. Owner field hours often go uncoded entirely, which inflates apparent recovery and hides the gap. Count them as paid field hours for this measurement even if the owner does not draw an hourly wage, or the number is fiction.
Seasonal swing. Recovery drops in slow periods because fixed daily overhead spreads across fewer coded hours. Measure in a normal period, and if you use one factor year-round, expect it to read light in the busy season and heavy in the slow one.
How to verify you got this right
- The gap reconciles: your category breakdown sums to the paid-minus-coded difference, with no unexplained remainder. A remainder means a category is missing, and the missing ones are usually the expensive ones.
- Your load factor is stated as paid divided by coded, and someone else in the shop can restate it as a recovery percentage without getting it backwards.
- The attackable pile is a separate list with owners and dates, not a line in the factor.
- Re-measured a quarter later, the factor moved in the direction your improvements predicted. If it did not move at all, either the improvements did not happen or the recovered time was absorbed rather than filled.
References
- U.S. Small Business Administration (SBA), overhead allocation and cost recovery for small business
- Standard construction estimating practice, labor productivity factoring and indirect cost allocation
- See related: The Job Costing SOP; How to Build a Labor Hour Database From Your Own Jobs; Labor Burden - The Real Cost of an Employee