A roofing job can be bid at a healthy margin, run with a good crew, and still finish 10 points below plan — and the cause usually isn't bad estimating. It's change orders that never got priced, signed, or invoiced. Rotted decking, a surprise second layer, a code-required flashing upgrade: the crew handles it because that's the right call in the field, but if it never becomes a documented change order, the cost lands on the job with no revenue to offset it. Multiply that across a season of jobs and it's the single most common margin leak we find in roofing company books that isn't caused by material prices or labor rates at all.

How Change Orders Quietly Erode Margin

The failure pattern is almost always the same. A crew lead finds rotted decking mid-tear-off, calls the office or the customer directly, gets a verbal "yeah, go ahead," and keeps working. Nobody writes down the square footage, nobody prices the extra labor, and nobody circles back to invoice it once the job wraps and everyone's already on the next roof. The cost was real — plywood, fasteners, an extra half-day of labor — but the revenue never showed up.

None of this shows up as a single dramatic loss. It shows up as a job that was bid at 38% and closed at 28%, with no obvious explanation on the invoice. Owners chase it in labor rates and material pricing when the actual leak is upstream, in the gap between what changed in the field and what got billed.

Worked Example: A $42,000 Job Loses 10 Points of Margin

Take a straightforward tear-off and reroof, bid at $42,000 with a budgeted 38% gross margin — meaning planned cost of $26,040. Over the course of the job, three change conditions come up:

Condition Found Added Cost Documented & Invoiced?
Rotted decking, 340 sq ft $1,394 No — verbal approval only
Unexpected second shingle layer $1,820 No — noted in field log, never priced
Code-required flashing upgrade $860 No — assumed "part of the job"
Total unbilled added cost $4,074

That $4,074 in real cost lands on the job with zero additional revenue. Total cost rises from $26,040 to $30,114 against the same $42,000 contract. The math: ($42,000 − $30,114) ÷ $42,000 = 28.3% actual gross margin — a full 10-point drop from the 38% that was bid, on a job the crew completed correctly and the customer was happy with.

💡 The scale problem: One job absorbing $4,074 is a rounding error. A crew of two doing this on even half their jobs across a 150-job season is six figures of margin that was earned in the field and never collected.

The Pricing Rule: Match Your Base Contract Margin

Even contractors who do write up change orders often underprice them. The common habit is "cost plus 10%" — charging a flat, thin markup because it feels fair for extra work. That still dilutes the job. If the base contract was priced to net 38% gross margin, a change order priced at cost-plus-10% only nets roughly 9%, and every dollar of change order revenue drags the job's blended margin down.

The fix is mechanical: price every change order at the same gross margin rate as the base bid. If the job was bid to net 38%, divide the added cost by 0.62 (1 minus 38%) to get the price to charge, not the cost plus a flat fee. On the $1,394 decking replacement above, that's a price of $2,248 rather than a cost-plus-10% price of $1,533 — the difference between a change order that protects your bid margin and one that quietly erodes it.

What a Valid Change Order Needs

A change order that actually protects your margin needs four things, captured before the extra work starts, not after:

  • Scope description: exactly what changed from the original contract, tied to a specific line item or area of the roof
  • Cost and price: the added cost to you, and the price to the customer calculated at your standard bid margin, not a flat markup
  • Signature before work begins: a text message approval or a one-page signed form works — a verbal "go ahead" does not hold up if the customer disputes the invoice later
  • A number: every change order gets a sequential ID (CO-1, CO-2) so it can be tracked, invoiced, and reconciled against the job cost report
💡 Field rule that works: No signed change order, no extra work starts — full stop. Crews resist this at first because it feels like it slows down the job, but it takes two minutes with a phone and it's the only thing standing between your crew doing the right thing in the field and your business eating the cost of it.

Tracking Change Orders in QuickBooks

In QuickBooks Online with Projects enabled, each approved change order should be entered as its own line item tied to the job's Project — not folded into the original estimate or absorbed into a generic "materials" expense. That keeps the Project Profitability report showing the true, updated contract value (original bid plus approved change orders) against true total cost, rather than measuring the job against a bid that scope has already outgrown.

Alongside QuickBooks, keep a simple change order log — number, date, description, cost, price, signed status, invoiced status — and reconcile it against each Project monthly. Any change order marked "signed" but not yet "invoiced" is revenue sitting on the table. At JobCostBooks, this reconciliation is part of the monthly job costing report on the Growth and Pro plans, so unbilled change orders get caught before the job closes, not after. For the underlying job costing setup this depends on, see our guide: QuickBooks Job Costing for Roofers: Step-by-Step Setup.