Skip to main content
2,200+ contractors in the research universe benchmarked. Do you know your gross profit per labor hour? See where you stand →
Level
Job Costing

Your Biggest Job Lost $47K. Here's How to Find Every Other One Hiding in Your Books.

Sam YangEx-CFO across trades, SaaS & services · $2.5B in total PE/banking transactions · Stanford MBA
Updated October 7, 2026·Originally published April 29, 2026·11 minute read
Share

From Level's proprietary contractor research

A revenue-only job report cannot show real margin. The costs exist in payroll runs and AP invoices, but they are never allocated. This is why your P&L can look healthy while individual jobs lose money invisibly.

Framework informed by research across 2,200+ contractors, $13.25B in job revenue analyzed

11 minute readJob Costing

If this is you

Fictional scenario. You closed the job. Invoiced $280K. Your estimate put cost near $271K, so you think you made $9K. Then your accountant allocates every payroll hour, AP invoice and receipt to the job, and actual direct cost comes to $327K: a $47K loss, 16.8% of revenue. Without job-level cost allocation, a gap like that tends to surface months later, if at all.

Across 1,747,089 completed jobs from 1,791 companies with job-level cost, per Level Index published metric (see its eligible sample and definition), Level measured a 44.3% median gross margin per job (revenue minus actual cost, before overhead allocation). In the same dataset, 6.2% of jobs had negative gross margin and 16% were below 20%, so a profitable company total can contain losing jobs. Revenue alone is not job costing. Labor, materials, subcontractor bills, and receipts must be allocated to the specific jobs that incurred them.

This is the phantom margin problem. Your P&L looks fine because total revenue minus total cost equals positive profit. But individual jobs, the ones you'd want to learn from, reprice, or investigate further, can be losing money invisibly.

If your biggest job last year quietly lost $47K, test whether the same leak shows up in others. One loser does not prove others exist, and a clean review of the next twenty jobs is a real answer. Here's how to check.

Why "feel" margins are wrong

Most contractors price jobs based on an estimating sheet that uses historical labor rates, materials at recent quoted prices, and a target margin. That gives you a quoted number.

When the job closes, you compare the quoted number to the invoiced number and call that "margin." If the customer paid what you quoted, margin is what you expected.

The problem: that math compares revenue to revenue. It tells you nothing about cost.

The real margin equation:

Real margin = Invoiced revenue − (actual labor + actual materials + actual subs + actual equipment + allocated overhead)

The first four cost terms give job gross margin, the same basis as Level's 44.3% job-level median. Subtracting allocated overhead gives margin after overhead, which always reads lower. Compare each against its own basis.

Many job reports miss several of those terms:

  • Unbilled labor. Techs spent 4 hours on a callback for this job that nobody charged. Level's billing capture metric (hours invoiced ÷ hours logged on jobs) had a median of 97.1% across 963 companies with at least 100 logged hours, per Level Index published metric (see its eligible sample and definition), with the 25th percentile at 89.2% and the 10th at 66.9%. That metric only sees hours someone logged to a job. A callback never coded to the job is invisible to it, so check uncoded time separately.
  • Materials waste. Job pulled $3K extra in materials due to a misread spec. Nobody coded that adjustment.
  • Equipment time. The truck was tied up on this job for 3 days. Cost it at an internal daily equipment rate. The revenue the truck might have earned on another route is an opportunity cost, not a job cost, so do not add both.
  • Allocated overhead. Office time, dispatch, supervision, all real, all costing real dollars, almost never allocated to specific jobs.

Each uncounted cost overstates margin by its size divided by revenue. Fictional example: on a $280,000 job, $14,000 of uncoded callback labor and materials overstates margin by 5 points ($14,000 ÷ $280,000). Your overstatement is something to measure, not a fixed range.

How to autopsy a single job in 90 minutes

Start with one job, the biggest one you closed in the last 6 months. Not the one that "felt" weird. The biggest one.

Step 1: Pull the actuals (30 min)

For this specific job, pull from each system:

Labor (from FSM or timesheets):

  • Every hour logged against the job number
  • Every overtime hour
  • Every "callback" or "rework" hour (often coded separately)
  • Every drive-time hour for techs going to and from the site
  • Burdened cost = hours × your direct labor cost rate: wage plus employer payroll taxes, workers' comp, benefits and, if you do not cost vehicles under Equipment below, a per-hour vehicle cost. Classify supervision by actual work: job-specific foreman time can be direct cost, while shared dispatch and office cost can be overhead. Any cost included here must be excluded from the overhead allocation below. Counting them in both places double-counts cost and makes profitable jobs look like losers. Fictional example: $30.00 wage + $2.70 payroll taxes + $2.10 workers' comp + $4.20 benefits = $39.00 per hour. Compute your own; there is no universal multiplier.

Materials (from AP or POs):

  • Every PO referencing the job
  • Every credit-card receipt that mentions the job
  • Every truck-stock pull that came off this job

Subs (from AP):

  • Every subcontractor invoice for this job

Equipment (from internal tracking or estimates):

  • Days of equipment use × daily allocation rate

Step 2: Add allocated overhead (20 min)

Take your last 12 months of overhead expenses (G&A, supervision, office, software, etc.) and divide by total direct labor hours from your jobs. That's your overhead-per-direct-labor-hour rate.

Multiply by direct labor hours on this specific job. That's the overhead you should allocate.

Fictional range for illustration: at $25 to $60 per direct labor hour, a job with 200 direct labor hours carries $5,000 to $12,000 of overhead. Your rate comes from your own books. Use the same definition of direct hours in the denominator and on the job, or the allocation is distorted.

Step 3: Calculate real margin (10 min)

Real margin = Invoiced revenue − (labor + materials + subs + equipment + overhead)

Compare to "feel" margin (what you thought it was). The gap is your blind spot on this specific job.

Step 4: Identify the leak (30 min)

Where did the real margin land vs. expected? The gap is one of:

  • Labor overrun: Took more hours than estimated. Compare actual job hours with the original estimate before attributing the difference to price.
  • Materials waste: Used more materials than budgeted, or got hit by price increase between quote and execution.
  • Scope creep: Did work outside the original quote that didn't get billed as a change order.
  • Compliance gaps: Held billing because of paperwork (waivers, COIs) and now collecting on stale work that's been "completed" for 60 days. This mainly delays cash rather than changing margin. It becomes a margin problem only if part of the invoice ends up uncollectible or written off.
  • Allocation surprise: Overhead is bigger than you thought.

Document which one was the dominant cause. This is your operational lesson for the next job like this.

Free benchmark review

See how your margins benchmark.

Start with a free conversation about your priorities. With agreed access to the relevant records, we compare your numbers with applicable benchmarks and identify what to review first.

How to find your other losers

Once you've autopsied one job and seen the gap between "feel" and reality, scale the process to your last 90 days of completed jobs.

Pull the list

From your accounting + FSM:

  • Every job that closed in the last 90 days
  • Revenue per job
  • Direct labor hours per job (from FSM)
  • Direct materials per job (from PO/AP)
  • Subs per job (from AP)

Calculate quick-and-dirty margin

Quick margin = Revenue − (labor hours × $burdened_rate) − materials − subs − (labor hours × overhead_per_hour)

This is margin after allocated overhead, not gross margin. Add job-specific equipment costs where recorded. For a gross-margin comparison, remove the overhead term and reconcile the remaining direct-cost classifications to the benchmark before comparing percentages.

This is approximate. It misses things like callback labor that wasn't coded to the job. But it's good enough to surface the obvious losers.

Sort by margin

Sort the list ascending. The bottom quartile (25%) by margin are your suspects. Mark each:

  • Negative after allocated overhead: Investigate the direct costs and the allocation before treating the result as a gross loss.
  • Bottom-quartile (positive but well below your target): Jobs that "made money" but underperformed. Investigate to find the leak before it spreads.
  • Top quartile: Don't ignore these, figure out what's working and replicate.

Pattern-match

Across your bottom-quartile list, look for patterns:

  • Customer: Does one customer dominate? You may have a customer-pricing problem (or a scope-creep problem with that specific customer).
  • Job type: Does one type of work dominate (e.g. all the install jobs are losers)? Pricing problem in that line.
  • Tech: Does one crew or one tech show up repeatedly? Operational discipline problem.
  • Geography: Does one region show up? May be a routing/density issue.
  • Season: Does timing matter (e.g. all the rushed end-of-quarter jobs)? Bidding-pressure problem.

The pattern tells you whether the leak is structural (pricing, customer, line-of-business) or episodic (one bad crew, one rough month).

What changes after the audit

Three diagnostic patterns to test for. These are possibilities to check, not measured frequencies:

Pattern 1: A customer or two is killing margin. Test: what share of your bottom-quartile jobs come from your one or two largest customers, compared with those customers' share of all jobs closed in the same 90 days? In a fictional comparison, 20% of all jobs but 60% of bottom-quartile jobs flags an association to investigate. Match scope, price, crew and complete cost before attributing the loss to the customer. Equal shares also do not rule out a customer effect. The fix: reprice on next renewal, fire the worst, or restructure the relationship.

Pattern 2: A specific service line is loss-making. Check install or large-project work. The fix: stop bidding it, or reprice it dramatically. If you are planning an exit, a loss-making line also weighs on whatever earnings measure a buyer uses, whether SDE or EBITDA. Do not assume a specific multiple for service-heavy or install-heavy work without a current valuation. Following the margin is also the exit-readiness move.

Pattern 3: Estimating discipline is broken across the board. Bottom-quartile jobs scatter randomly across customers and types. The fix is operational: tighten estimating, weekly variance review, post-mortems on every job where actual direct costs run more than 10% over the estimate.

Each pattern has a different fix and different timeline.

The 90-day discipline that prevents this

After the audit, the operational discipline that keeps you from re-creating the problem:

  1. Every timesheet codes to a job. No exceptions. If a tech is in the truck driving between jobs, that time codes somewhere.
  2. Every PO references a job. Truck-stock pulls get reconciled at month-end and allocated.
  3. Every credit-card receipt gets allocated within 7 days. The further out, the harder to remember why it was bought.
  4. Weekly job-margin report. Every Monday morning, the team reviews completed jobs from the prior week with revenue, cost, and margin. Bottom 10% gets a 5-minute root-cause discussion.
  5. Post-mortem when actual direct cost exceeds the estimate by more than 10%. Not blame. Pattern recognition. What estimating assumption was wrong? What changed mid-job? How do we catch it earlier next time?

Many shops with broken job costing already own a tool that can tag costs to jobs, such as ServiceTitan, BuildOps or QuickBooks Projects, depending on edition and setup. Often the tooling isn't the problem. The closed loop between field, ops, and accounting is. A job-level review closes that loop.

Start with the find-your-gap tool, then compare your own job gross margins with Level's measured job-level distribution: median 44.3% and 25th percentile 28.4% across 1,747,089 completed jobs from 1,791 companies, per Level Index published metric (see its eligible sample and definition). Or book a free 30-min audit to walk through the allocation steps above using your own last 90 days of jobs.

Share

Get the next one

Want next week's benchmark in your inbox?

One email a week. Real numbers from 2,200+ contractors in the research universe. No fluff. Unsubscribe anytime.

Sam Yang

About the author

Sam Yang

Founder & CEO

Founder of Level, the always-on finance team for contractors, service businesses, and ecommerce brands. Ex-CFO across trades, SaaS, and service businesses. 4 years as Director of Growth Product at BuildOps, building financial tooling used by 1,000+ commercial contractors. Four years in PE and investment banking rolling up and acquiring service businesses, $2.5B in total transactions including M&A and IPOs. Stanford MBA, Brown undergrad. The Level founding team's analysis of 2,200+ contractors ($13.25B in job revenue) across operating, private-equity, and CFO roles anchors the Level Index benchmark research.

LinkedIn

See how your margins benchmark.

Start with a free conversation about your priorities. With agreed access to the relevant records, we compare your numbers with applicable benchmarks and identify what to review first.

2,200+ businesses benchmarked$13.25B in revenue analyzedWeekly action cadence

No credit card. Start with a 15-min call. We only follow up if we can actually help.

No commitment. Real numbers, not generic advice.