Your Material Markup Isn't a Strategy — It's a Guess
Your Material Markup Isn't a Strategy — It's a Guess
In the fall of 2019, I was part of the team at Atlantic Comfort Partners reviewing a 14-truck residential HVAC shop ahead of acquisition. The owner knew his business. His trucks were clean, his Google reviews were solid, and his material markup was a consistent 50%. Nothing looked obviously broken.
It took about four hours with his job-level P&L to find the problem. He had been losing money on every install for three years. The service department's margins had been quietly subsidizing the install side, and the blended gross margin number — the one he looked at monthly — made everything appear functional. The material markup wasn't the cause. But it was where the problem hid.
That shop is the reason I write about this.
The Markup Number Isn't the Problem — Your Cost Model Is
Most contractors set their material markup by copying whoever came before them. The previous owner charged 50%, so 50% it is. A vendor rep suggested 100% keystone, and that became the standard.
Neither source is connected to your actual overhead structure. That's the problem.
A markup percentage is supposed to answer a specific question: given what I paid for this part, what do I need to charge to cover the full cost of getting it to the job and still have margin left? If you can't describe your answer in terms of your own shop's numbers, the markup you're using is a guess dressed up as a policy.
The recurring problem I find in cost-of-doing-business reviews is that shops conflate markup with margin and set one number for all materials regardless of category. The 14-truck shop had a 50% markup that looked, in isolation, reasonable. What it didn't capture was the full cost of carrying those materials to the job — and more specifically, how dramatically that cost differed between a service call and an equipment install.
The number on its own isn't the problem. The absence of a cost model underneath it is.
What "Material Cost" Actually Includes
When a contractor says their material cost on a job was $800, they usually mean the supply house invoice said $800. That's a starting point. It is not a complete number.
Supplier terms and foregone discounts. If your supplier offers 2/10 net 30 and you're paying on day 28, you're leaving 2% on the table. If you're borrowing on a line of credit to fund operations, the interest cost of not taking that discount is higher than it looks.
The capital cost of truck stock and warehouse inventory. Inventory sitting on a shelf — or in a van — is money you spent that hasn't billed yet. This connects directly to the cash conversion cycle. Stock a van with $6,000 in parts turning every 45 days and you're financing $6,000 for 45 days on every rotation. Most shops don't calculate that carrying cost and don't build it into the markup.
At Bayview Mechanical in Sunnyvale, we pulled from the supply house daily for most service work. At Caldera, we ran stocked vans on a weekly replenishment cycle. The carrying cost model for those two approaches is meaningfully different. Daily supply house runs cost you windshield time and same-day premium pricing on some SKUs. Stocked vans cost you tied-up capital, shrinkage, and parts that age out on the shelf. The markup has to reflect which model you're actually running, because the embedded costs are not the same.
Return freight and defective parts. A compressor that comes back defective costs you a return trip, a supply house credit that takes 30 days to appear, and a callback that usually doesn't get billed. That cost lives somewhere. If it's not in your material markup, it's absorbed into labor, which means your labor margin is hiding a materials problem.
Shrinkage and misallocation. Parts used but not billed. Parts pulled for a job that don't make it onto the invoice because the tech moved on. This is real spend that has to come from somewhere in the margin stack.
The PE Acquirer Sees It Immediately — And You Probably Don't
When the Atlantic Comfort Partners team reviewed a target shop, one of the first things we did was pull gross margin on installs and service calls separately. Not blended. The blended number almost always looked acceptable. The separated numbers almost always told a different story.
Material markup inconsistency showed up on the install side more than anywhere else. Shops running a flat markup on all materials were cross-subsidizing install margins with service margins — and had no idea. A service call involves a small part, a fast turn, limited capital tied up per ticket. A residential install involves equipment, extended billing cycles, and real capital sitting between purchase order and invoice. A 50% markup treats both identically. The math doesn't support that.
The acquirer's letter of intent will reflect this problem whether or not the seller can name it. The buy-side valuation model haircuts the install gross margin assumption and tightens the EBITDA multiple on that segment. The offer comes in below what the owner expected. The owner asks why. The answer is buried in four years of install job costing he never separated from service.
I saw this in deal after deal at Atlantic Comfort Partners. It was not the exception. And it's visible — entirely visible — if you look at the right reports before someone else does.
The Contrarian Position: A Higher Markup Percentage Can Actually Hurt You
The instinct, when someone shows you that your material margins are soft, is to raise the markup. Just go from 50% to 65% and call it fixed.
That produces the wrong result on most SKUs — and in opposite directions.
On commodity parts your customer can price on Google or that three competitors stock on their trucks, a higher flat markup prices you out of jobs. A $14 capacitor marked up 100% to $28 is fine. The same capacitor at 130% becomes $32.20 — a line item that reads as gouging to someone who just Googled it.
On specialty or emergency-sourced parts, the opposite problem applies. A $4,200 variable-speed blower motor that took 11 days to source, required freight, and absorbed two hours of your service manager's time to track down should carry a margin that reflects that actual cost. A flat percentage doesn't do that math. It produces a number that may or may not be adequate, and you won't know until you look job by job.
The flat-rate pricing books sold by major industry vendors have the same structural flaw. They produce predictable revenue per ticket and unpredictable margin per ticket. A blanket markup applied across a full parts catalog works the same way. Predictable revenue is not the goal. Predictable margin is.
The SEER2 transition illustrated this clearly. Equipment costs went up on split systems, sometimes significantly. Shops that applied their existing flat markup percentage to the higher equipment cost recovered some dollars. But the percentage didn't account for the increased capital tied up per unit while jobs waited on installation scheduling, or the financing cost when equipment sat in a warehouse for two weeks between arrival and install. Shops that adjusted their margin target in dollar terms came through in reasonable shape. Shops that absorbed the cost increase and called it temporary are still waiting for the margin to come back.
What to Track Instead: Material Margin Dollars by Job Category
The replacement metric isn't a different percentage. It's margin dollars, tracked by job category, with material cost as a percentage of job revenue calculated separately for each category.
Maintenance, service repair, and residential install have genuinely different material cost structures. Tracking them together produces a blended number that masks performance in every segment. If you also do light commercial, that's a fourth category with its own profile.
For each category, over a rolling 90 days: total material revenue billed, total material cost at invoice, material margin dollars, material margin percentage. That's the first pass.
Second pass: estimate the carrying cost for that category's inventory model and add it to the material cost figure. The gap between first pass and second pass is the carrying cost burden — the cost your markup has to cover before you have margin to keep.
When I ran this separation on the 14-truck shop's P&L for the first time, installs were running 11 points below where the owner believed they were. The blended material margin looked acceptable — around 38%, which felt fine — because service was sitting closer to 49% and pulling the average up. He had never seen the separated number. His software wasn't set up to produce it, and nobody had asked the question before.
Those 11 points on installs, on a shop doing roughly 200 installs a year — and I'm using round numbers here for illustration, not the shop's exact figures — represented a material underperformance that showed directly in the acquisition offer. That's not a rounding error. It's a number that changes what the business is worth.
What to Do Monday Morning
Pull the last 90 days of closed jobs from whatever system you run. You need two columns per job: total material cost and total material billed. Then sort by job type.
If you're on ServiceTitan and your job categories are set up correctly, the reporting suite can produce this breakdown. If nobody on your team knows how to pull it, that's useful information in its own right — the platform isn't being used at the level that justifies the subscription, and that's a management gap with a real cost attached.
If your categories aren't clean enough to trust the output, do it manually on 20 jobs. Ten installs and ten service calls. Invoice cost for materials on each, what you billed the customer for materials, the difference. That sample is enough to tell you whether a problem exists and roughly how large it is. You don't need 90 days of clean data to see that your install material margins are running 12 points below your service margins.
Once you have the category-level numbers, look at the installs separately. Calculate the material margin percentage for that group alone. Then: does that number cover your carrying cost for the equipment and materials associated with installs? If you're stocking anything for install jobs — equipment in a warehouse, line set on a rack, anything — estimate what you spent to finance that inventory over the period. Divide it by install material revenue over the same period. That's your carrying cost as a percentage of install material revenue. If it's higher than the cushion built into your current markup, you've found the leak.
Start there. The markup number comes after.
FAQ
My supplier gives me a standard markup guide — why isn't that good enough?
The supplier's markup guide is calibrated to their interests. It's designed to position their products competitively and help you win jobs, both of which benefit the supplier. It has no relationship to your overhead structure, your carrying cost model, your return rate on defective parts, or what it costs you to stock a van versus running to the supply house. It tells you what the market will bear on a given part. It's a poor substitute for a cost model built on your own numbers.
How do I account for parts I stock on the truck versus parts I run to the supply house same-day?
They carry different costs and deserve different markup treatment. Truck-stocked parts have a carrying cost — tied-up capital, shrinkage, aging — that should be estimated and built into the markup for that category. Supply house same-day pulls carry a different cost: the windshield time to make the run, any same-day premium on the part, and the risk of a second trip if the first pull was wrong. Neither is free. The markup for each should reflect its actual cost structure rather than a single number applied to both.
What's a reasonable material margin percentage for residential HVAC installs versus service calls?
I won't give you a benchmark number pulled from my experience and dropped into your context, because that's exactly the kind of shortcut this article argues against. What I can tell you is that install margins and service margins are structurally different — installs carry more capital exposure per job, longer billing cycles, and more freight and handling risk — so if yours are running the same or reversed, that's worth examining before you assume it's correct. Build the category-level view first. The right number for your shop comes out of your own data.
If I raise my parts prices, won't I just lose jobs to competitors who are cheaper?
On commodity parts with visible pricing, yes, there's price sensitivity. The answer isn't to underprice those parts — it's to compete on speed, warranty, or relationship, and to make sure your labor rate is carrying appropriate margin so you're not dependent on material margin to cover overhead. On specialty, emergency-sourced, or high-cost equipment, customers have much less price sensitivity than contractors assume. The shop that gets the right part in two days charges more than the one that takes two weeks. That premium is real and defensible.
How does inventory on the balance sheet connect to what I see on my P&L margin?
Inventory on the balance sheet is parts you've bought but not yet billed. It doesn't hit your cost of goods sold until the job closes. This means if you're sitting on $40,000 in equipment between purchase and install, your P&L looks better than your cash position — you've spent the money but haven't recognized the cost yet. When the job closes, the cost drops into COGS and the margin on that job reflects the full part cost. If your install completion cycle is slow and you're carrying real equipment inventory, your days sales outstanding and your cash conversion cycle deserve a close look. The P&L won't show you the problem until it's already a cash problem.
Should I be pricing materials differently on maintenance agreements versus time-and-material calls?
Yes. Maintenance agreement customers have already committed to a price, which means your material cost on those visits has to fit within the agreement revenue — you're not marking materials up separately because the invoice is already fixed. Your agreement pricing has to account for expected material consumption, including consumables like filters, drain treatments, and capacitors that fail on aging equipment. On time-and-material calls, the markup conversation applies directly. Running both pricing models without distinguishing them in your job costing means one side is subsidizing the other. The category-level breakdown will tell you which direction the subsidy is running.
Enjoyed this article?
Get articles like this in your inbox every Monday. Free, no spam.
