Most HVAC pricing lives in two disconnected worlds. Finance knows the real cost-to-serve — labor-loaded hours, drive time, parts markup, warranty exposure. Dispatch and sales set prices, pick zones, and apply discounts based on gut feel and whatever the competitor down the street is charging. These two worlds almost never talk to each other, and the gap between them is where margin quietly disappears.
The problem isn't that HVAC owners don't understand their numbers. Plenty do. The problem is there's no operating model — no shared inputs, no agreed-upon routing math, and no approval gates that stop a fair price from turning into a bad one once a long drive, a zone surcharge, or a "just give them 10% off" decision gets layered on top.
This is a playbook for building that bridge. Not a pricing theory lecture — a practical model that defines the canonical inputs everyone pulls from, the routing-impact calculus that adjusts price by geography, and the approval gates that keep discretionary decisions from eroding profit. If you've already built a cost-to-serve model, this sits on top of it and turns those numbers into daily pricing and dispatch decisions.
Why pricing and routing are actually the same decision
Price and route aren't separate problems. The profitability of a job is largely set the moment you commit a truck to a location at a quoted price. Everything after that — the diagnosis, the repair, the upsell — moves the number a little, but the big swing happened at booking.
Consider two identical capacitor replacements. Same part, same labor, same flat rate of $340. One is twelve minutes from the tech's previous stop. The other is a 55-minute one-way drive into a rural zone with no other jobs nearby. On paper, both look like $340 jobs with the same margin. In reality, the second job carries roughly 90 extra minutes of paid, non-billable drive time plus the opportunity cost of a slot you can't fill with a closer call. That's easily $70–$110 of hidden cost the flat rate never accounted for.
What tends to happen across service businesses is that this invisible drive-time tax gets socialized across all jobs. The dense, efficient city routes subsidize the sparse outlying ones. Customers five minutes away pay the same as customers an hour out, which means your easiest-to-serve customers are effectively funding your worst. Nobody designed it that way. It just happens when pricing and routing never share a formula.
The canonical inputs: one source of truth
Before you can run any pricing or routing calculus, everyone in the business needs to pull from the same definitions. This sounds obvious until you ask three people what a "billable hour" costs and get three different answers.
Eliminate scheduling chaos and missed jobs.
Coolyly helps HVAC companies book, coordinate, and track every service efficiently.
- Unified appointment & dispatch management
- Automated client notifications
- Technician scheduling & job tracking
No credit card required
A canonical input set means finance, dispatch, and sales agree on a single fully-loaded number for each cost driver. Not a budget figure, not a wishful figure — the real one, reconciled monthly against actuals.
-
Loaded labor rate per tech hour — base wage, payroll tax, benefits, PTO accrual, and a share of non-billable time (training, shop time, callbacks). For a tech paid $32/hr, the loaded number often lands somewhere between $52–$61/hr depending on your utilization.
-
Drive-time cost per minute — loaded labor plus vehicle operating cost (fuel, maintenance, depreciation) divided across productive minutes. Usually around $0.90–$1.40 per minute once you include the van.
-
Parts cost and standard markup bands — actual landed cost including freight and shrinkage, not catalog price.
-
Warranty and callback reserve — a percentage of revenue set aside per job class, based on your actual callback rate for that work type.
-
Overhead absorption per billable hour — rent, software, admin, insurance, spread across expected billable hours.
-
Target contribution margin by job class — maintenance, diagnostic, repair, and install each get their own floor.
The discipline here is that these numbers get updated on a schedule, not argued about per-job. When a dispatcher quotes a price or a manager approves a discount, they're applying a model, not reinventing one. This connects directly to a solid month-end job-margin process — the inputs here feed off those reconciled actuals.
A quick note on getting these numbers wrong
The most common mistake isn't using bad inputs. It's using stale ones. A shop sets its loaded labor rate in January, fuel jumps 20%, two techs get raises, and by August the drive-time cost per minute is off by a third. Every rural job quoted after that is underpriced and nobody notices until the quarter closes soft. Canonical inputs are only useful if someone's keeping them alive.
The inputs themselves aren't complicated. What's hard is the organizational habit — someone has to own the update cycle, and it has to actually happen. Without that, the model drifts and people stop trusting the numbers, which means they stop using them.
Routing-impact calculus: pricing the distance
Once you have a drive-time cost per minute, you can build the routing-impact layer. The goal is simple: every job's price should reflect the real cost of getting a truck there and the opportunity cost of the slot it consumes.
The core formula:
Routing-adjusted cost = base job cost + (drive minutes × drive-cost per minute) + slot-opportunity penalty
The slot-opportunity penalty is what most shops skip, and it's the one that matters most during busy season. When you're at capacity, a far-out job doesn't just cost its own drive time — it blocks you from booking a closer, more profitable call. That penalty should scale with how full your schedule is. On a slow Tuesday in shoulder season, the penalty is near zero. On a 95%-booked July afternoon, it's real money.
| Job | Flat Rate | Drive (min, round trip) | Drive Cost | Slot Penalty (peak) | True Cost | Real Margin |
|---|---|---|---|---|---|---|
| City capacitor | $340 | 20 | $24 | $0 | $198 | ~42% |
| Suburban capacitor | $340 | 50 | $60 | $15 | $249 | ~27% |
| Rural capacitor | $340 | 110 | $132 | $45 | $351 | negative |
Same job, same flat rate, three completely different outcomes. The rural call loses money at peak once you factor in full routing impact. This is exactly why flat-rate-only pricing breaks down as you expand your service territory — it was never designed to carry geography.
The fix isn't to stop serving far customers. It's to attach a zone modifier so the price reflects the cost. The table makes it obvious, but in daily operations that math is invisible — which is why it keeps getting ignored.
This diagram shows the routing-impact calculation workflow in a simple flow.
Zone modifiers and the discretion problem
Zone modifiers are surcharges applied by geography. A tiered system might look like: Zone 1 (core, 0–20 min) no modifier, Zone 2 (20–40 min) +$35, Zone 3 (40+ min) +$75 or a trip-minimum. Simple enough as a concept.
The failure point is enforcement. In real operations, the modifier gets waived constantly — a dispatcher wants to be accommodating, a salesperson wants to close, a repeat customer complains. Each waiver feels reasonable in the moment. Stacked across a few hundred jobs a month, the leakage is substantial. A shop running around 400 jobs a month with a Zone 2/3 mix might apply roughly 70 modifiers; if a third get quietly waived, that's $1,500–$2,500 a month walking out the door, invisible because it never shows up as a line item.
Approval gates that actually hold
-
Auto-approved — modifiers and markups inside the canonical bands. No human in the loop. A Zone 2 surcharge applied at booking, a standard parts markup — these just happen.
-
Dispatcher discretion, logged — small concessions within a capped dollar amount (say, up to $25 off), but every one is recorded with a reason code. The cap and the logging are what matter; unlogged discretion is how leakage hides.
-
Manager gate — anything that pushes a job below its target contribution floor, waives a full zone modifier, or exceeds the discretion cap. Requires explicit approval tied to a reason: competitive match, service recovery, strategic account.
-
Owner/finance gate — below-cost pricing, standing discounts for a whole account, or any pattern that would change the canonical model itself.
The point isn't bureaucracy. It's that the decision to give away margin gets made by whoever answers for margin. When a dispatcher can waive a $75 zone fee with no log and no cap, the model is decorative. When that same waiver requires a reason code and rolls up to a weekly report, discipline follows almost on its own.
A decision table for common pricing actions
Here's how the gates map to the pricing moves that come up every day. Worth printing and keeping near the dispatch desk.
| Pricing Action | Condition | Gate | Required Reason |
|---|---|---|---|
| Apply standard zone modifier | Job in Zone 2/3 | Auto | — |
| Waive zone modifier | Repeat customer, close call | Dispatcher (logged) | Loyalty / proximity |
| Discount up to $25 | Minor service recovery | Dispatcher (logged) | Recovery code |
| Discount $25–$100 | Competitive quote | Manager | Competitor name + price |
| Price below contribution floor | Strategic/large account | Owner | Account strategy note |
| Bundle discount on install | Multi-system quote | Manager | Bundle math attached |
| Emergency after-hours rate override | Customer dispute | Manager | Dispute notes |
The value of a table like this is that it removes the argument. Nobody debates whether a $60 competitive discount needs sign-off — the table already settled it. That consistency is what lets a growing shop maintain pricing discipline even when the person booking the job is three months into the role. It also creates a paper trail, which matters when you're trying to figure out why a month came in soft.
What breaks as you scale
A two-truck shop can run all of this in someone's head. The owner knows every zone, every repeat customer, every price exception, because he's touching most of the decisions. The model lives in his memory and it mostly works.
At six, ten, fifteen trucks, that breaks completely. Multiple dispatchers, maybe multiple territories, a sales team — nobody holds the whole picture anymore. The informal rules one owner enforced by instinct get interpreted differently by five different people. Zone modifiers drift. Discounts creep. The same job gets priced three different ways depending on who answers the phone.
This is the scale wall where service economics either becomes a system or becomes chaos. The shops that cross it well externalize the model — canonical inputs in a shared place, routing math built into how jobs get quoted and dispatched, and approval gates enforced by the booking workflow rather than whoever happens to be paying attention. This connects directly to the case for rule-driven dispatch and scheduling: once routing and pricing share a rule set, the system can flag an underwater job before the truck is ever committed.
It gets harder still when you run a mixed book. Residential flat-rate and commercial contract work have completely different cost-to-serve profiles and routing logic, and a single undifferentiated model will misprice both. If that's your situation, the service-portfolio strategy for mixed residential-commercial shops pairs directly with this — separate canonical inputs per line of business feeding one shared gate structure.
When this model makes sense — and when it doesn't
When it's worth building: You're past three or four trucks, you serve a geography wider than a tight metro core, and you've noticed that some months are busy but soft on margin. If dense and sparse jobs carry the same price, and discounts go out without a trail, you're leaking and this fixes it.
When it's overkill: A single-truck owner-operator in a compact service area doesn't need zone modifiers and four-tier approval gates. The overhead of running the model would cost more than the leakage it prevents. Keep it simple, revisit when you add the second and third truck.
Who should be careful: Shops with a thin, loyal customer base in a rural market. Aggressive zone surcharges can read as punishing your most isolated customers, and if they're your bread and butter, you may price yourself out. The model still applies — you just need to decide consciously which routing costs you'll absorb as a relationship investment, rather than letting them leak unconsciously.
A real scenario
A regional HVAC shop running nine trucks across a spread-out county was booking strong — around 380–420 jobs a month — but summer margin kept landing weaker than the volume suggested. On paper, every job type hit its flat-rate target. The numbers just didn't flow to the bottom line.
When they rebuilt their inputs and ran the routing-impact math, the picture was pretty clear. Roughly a quarter of their jobs were in outlying zones with no modifier attached, and drive time on those calls was eating 15–20% of what looked like solid margin. A spot-check of a few weeks of bookings also showed dispatchers waiving the trip minimum on more than half of the far-out calls — nobody had ever told them not to, so they did the friendly thing.
They didn't do anything dramatic. Three-zone modifier, dispatcher discretion capped at $25 with a mandatory reason code, anything below the contribution floor routed to a manager. Within about two months, far-zone jobs were either carrying their cost or getting consolidated into tighter routes, and the discount leakage mostly stopped once every waiver had a name and a reason attached. The margin improvement was in the mid-single-digit percentage range on affected jobs — not a windfall, but on a few hundred jobs a month it added up to real money that had simply been invisible before.
The interesting part wasn't the surcharge. It was that making the gates visible changed behavior on its own. Once dispatchers knew waivers were logged and reviewed, most of the casual giveaways stopped before any manager had to say a word.
Pulling it together
Service economics in HVAC isn't a pricing problem or a routing problem in isolation — it's one decision wearing two hats. The price you quote and the truck you send either make money together or lose it together, and treating them as separate problems is how good-looking volume turns into a disappointing quarter.
The operating model is three connected pieces: canonical inputs that everyone trusts and that stay current, a routing calculus that prices distance and slot-opportunity honestly, and approval gates that put margin decisions in the hands of people accountable for margin. None of it is complicated math. The hard part is defining the inputs once, enforcing the gates consistently, and keeping the whole thing current as fuel costs, wages, and your service map shift underneath you.
Start with the inputs, because nothing downstream works without them. Then layer the routing math, then the gates. Build it before you hit the scale wall, not after — because once five people are pricing jobs five different ways, you're not fixing a model anymore, you're rebuilding trust in your own numbers.
Start with the inputs, because nothing downstream works without them. Then layer the routing math, then the gates. Build it before you hit the scale wall, not after — because once five people are pricing jobs five different ways, you're not fixing a model anymore, you're rebuilding trust in your own numbers.
Ready to optimize your HVAC operations?
Join hundreds of HVAC businesses using Coolyly to save time, improve technician utilization, and enhance customer satisfaction.