Construction · Job cost

Job cost variance

The difference between what a job was budgeted to cost and what it is now expected to cost. It is the main early warning a contractor has that a job is going off track.

Plan your metrics

What it is

Every construction job starts with a budget, broken down by cost code (concrete, framing, electrical, and so on). As work happens, costs post against those codes and the project manager updates an estimate of what is left to spend.

Job cost variance compares the two views: the budget, adjusted for approved change orders, and the projected final cost. It is usually reviewed for each open job every month, then rolled up by project manager, division, and company.

Why operators track it

  • It catches overruns while there is still time to act. An overrun found early can be managed through scope, crew, or change orders. Found late, it is much harder to recover.
  • It drives projected margin. If a job will cost more than budgeted and the contract value has not changed, the expected margin shrinks by the same amount.
  • It feeds the WIP schedule. Projected cost at completion is also the denominator for percent complete, which drives earned revenue and over/under billing.
  • It improves the next bid. Variance by cost code shows estimators which assumptions were wrong.

How it is calculated

Job cost variance = revised budget − estimate at completion

  • Revised budget = original budget + approved change order budget
  • Estimate at completion (EAC) = cost to date + estimated cost to complete
  • Variance % = job cost variance ÷ revised budget

The estimated cost to complete comes from the project manager's forecast, not a formula. That is deliberate: it captures what the PM knows about the work remaining.

Worked example

Job 2417 has an original budget of $1,200,000. Approved change orders add $80,000, so the revised budget is $1,280,000. Cost to date is $910,000 and the PM expects $420,000 more, so EAC is $1,330,000.

1. One job, by cost code: revised budget vs estimate at completionRevised budgetEstimate at completion (cost to date + cost to complete)Site work+$12,000Concrete labor−$62,000Concrete material$0All other codes$0Job 2417 total$1,280,000 budget − $1,330,000 EAC = −$50,000 (3.9% over)2. The same job over time: projected variance as the job progresses$0−$25,000−$50,0000%25%50%75%100%Percent completeAt 35%: −$10,000. Still time to act.At 68%: −$50,000
Example data Job 2417. Concrete labor is driving the overrun. The second panel shows why reviewing variance monthly matters: the overrun was visible at 35% complete.

How to read it

  • Positive means under budget, negative means over under the convention used here (budget minus cost). Some teams flip the sign. Pick one and label every chart.
  • The trend matters more than the level. A job sitting at −2% for six months is a different situation from one that moved from 0% to −2% last month.
  • Look at cost codes before conclusions. A small total variance can hide a large overrun in one code offset by savings in another.
  • We do not publish a "good" range. CFMA's Construction Financial Benchmarker covers related profitability ratios; we will cite it once we confirm citation terms.

Definitional choices and common pitfalls

  • Variance at completion vs cost-to-date variance. This page uses budget vs projected final cost. Some teams compare budget × percent complete to cost to date instead, when they trust physical percent complete more than PM forecasts.
  • Pending change orders. Including unapproved change orders makes the budget look healthier than it is. Excluding them can make a job look over budget for work the owner will likely pay for. Many teams show pending change orders as a separate column.
  • Committed cost. Purchase orders and subcontracts that are signed but not invoiced are not cost to date. They are useful as a check on the cost-to-complete estimate.
  • Stale forecasts. If PMs do not update cost to complete, EAC stays flat and overruns stay hidden.

How different roles use it

Role How they use it
Owner / CEO Scans the company roll-up and the few jobs with the largest negative variance.
CFO / controller Reviews every open job monthly, checks forecasts are current, and ties variance to projected margin and the WIP schedule.
Project manager Owns the forecast for their jobs and works cost code by cost code to explain and correct variance.
Estimator Reviews variance on finished jobs to adjust unit costs on future bids.

Questions it answers

  • Which open jobs are projected to finish over budget?
  • Which cost codes are driving the overrun?
  • Did any job move significantly since last month?
  • Which PMs' forecasts tend to hold up?

How to present it in a report

  • Start with a table of open jobs: revised budget, EAC, variance in dollars, variance as a percent. Sort by largest negative variance.
  • Let the reader drill from a job into its cost codes.
  • Show the change since last month next to the current value.
  • State the sign convention and whether pending change orders are included at the top of the report.

Data you need

Fields

Field What it means Example value
Job The project, with its PM and division Job 2417, PM: R. Diaz
Cost code A category of work in the budget 03-300 Concrete labor
Original budget Budget for the code when the job started $320,000
Approved change order budget Budget added or removed by approved change orders $0
Cost to date Posted cost from payroll, AP, and equipment $270,000
Estimated cost to complete The PM's forecast of remaining cost, by period $112,000
Change order status Pending, approved, or rejected Approved

What the raw data looks like

Example data A few rows as they might come out of the source system.

Job Cost code Original budget Approved CO budget Cost to date Cost to complete Period
2417 02-200 Site work $170,000 $10,000 $160,000 $8,000 Oct
2417 03-300 Concrete labor $320,000 $0 $270,000 $112,000 Oct
2417 03-100 Concrete material $210,000 $50,000 $200,000 $60,000 Oct
2417 All other codes $500,000 $20,000 $280,000 $240,000 Oct

Where this data usually lives

  • Construction ERP and accounting holds budgets, job cost, change orders, billing, and retainage. For example: Sage 300 Construction and Real Estate, Viewpoint Vista (Trimble).
  • Project management often holds change orders and their status, and sometimes budgets and forecasts. For example: Procore.
  • Estimating produces the original budget by cost code before the job starts.
  • Payroll and time tracking feed labor cost and hours to job cost.
  • Spreadsheets often hold the PM's cost-to-complete forecast or the WIP schedule itself.

The same field can live in more than one system. Agree with the customer which one is the source of truth.

Common data gaps and traps

  • Change orders not entered. Field work on a change that has not been written up makes the job look over budget.
  • Forecasts not updated. If cost to complete is stale, the estimate at completion stays flat and overruns stay hidden.
  • Forecasts kept outside the system. Some PMs keep cost to complete in a spreadsheet. Ask where it lives.
  • Cost codes that do not match. Actual cost posted to a code with no budget line drops out of a simple join.
  • Committed cost mixed into cost to date. Purchase orders and subcontracts not yet invoiced are not cost to date.
  • WIP over/under billing: uses EAC to compute percent complete.
  • Gross margin by job: variance flows straight into projected margin.
  • Labor productivity by cost code: often the cause of labor variance. Coming soon.
  • Change order cycle time: slow approvals keep revised budgets out of date. Coming soon.

FAQ

What is a good job cost variance?
Zero or positive. The more useful question is whether the variance is changing month over month. Projected margin that keeps fading is a warning sign.
Is job cost variance the same as cost variance in earned value?
They are related. Earned value cost variance is earned value minus actual cost to date. Job cost variance at completion compares budget to projected final cost.
Should committed costs be included?
Not in cost to date. Committed but uninvoiced costs are better used to sanity check the cost-to-complete estimate.
How often should job cost variance be reviewed?
Monthly at minimum, aligned with the WIP schedule. Weekly on large or troubled jobs.
For your data teamFormula variants, tables, SQL sketch, and dashboard spec

Formula details

revised_budget          = original_budget + approved_change_order_budget
estimate_at_completion  = cost_to_date + estimated_cost_to_complete
job_cost_variance ($)   = revised_budget - estimate_at_completion
job_cost_variance (%)   = job_cost_variance / revised_budget * 100
  • Sign convention: this page uses budget minus cost, so negative = over budget. Some teams flip it. Pick one and label it on every chart.
  • Estimated cost to complete comes from the PM's monthly forecast, not from a formula. That is the point: it captures what the PM knows.

Variants

Variant Formula Use when
Variance at completion (above) revised budget minus EAC Monthly job review, WIP
Cost-to-date variance (revised budget x percent complete) minus cost to date You trust physical percent complete more than PM forecasts
Earned value cost variance (CV) earned value minus actual cost You run earned value management
Cost code variance same formula at cost code grain Finding which scope is causing the overrun

Worked example detail

Job 2417: original budget $1,200,000. Approved change orders add $80,000 of budget. Revised budget: $1,280,000. Cost to date: $910,000. PM estimates $420,000 to complete. EAC = $1,330,000. Job cost variance = 1,280,000 - 1,330,000 = -$50,000, or -3.9% (over budget). Drilling into cost codes shows concrete labor is -$62,000 and site work is +$12,000.

Tables and fields

Table Fields Notes
jobs job_id, name, pm_id, division, status, contract_value
job_budget job_id, cost_code, cost_type, original_budget Labor, material, subcontract, equipment, other
change_orders co_id, job_id, cost_code, budget_amount, revenue_amount, status, approved_at Only approved COs move the revised budget
job_costs job_id, cost_code, cost_type, amount, posted_at AP, payroll, equipment charges
cost_forecasts job_id, cost_code, period, estimated_cost_to_complete PM monthly forecast

SQL sketch

WITH budget AS (
  SELECT b.job_id, b.cost_code,
         SUM(b.original_budget) AS original_budget
  FROM job_budget b GROUP BY 1, 2
),
cos AS (
  SELECT job_id, cost_code, SUM(budget_amount) AS approved_co_budget
  FROM change_orders
  WHERE status = 'approved' AND approved_at <= :as_of
  GROUP BY 1, 2
),
actuals AS (
  SELECT job_id, cost_code, SUM(amount) AS cost_to_date
  FROM job_costs WHERE posted_at <= :as_of GROUP BY 1, 2
),
ctc AS (
  SELECT job_id, cost_code, estimated_cost_to_complete
  FROM cost_forecasts WHERE period = :period
)
SELECT
  j.job_id, j.pm_id, j.division, b.cost_code,
  b.original_budget + COALESCE(c.approved_co_budget, 0)                AS revised_budget,
  COALESCE(a.cost_to_date, 0) + COALESCE(f.estimated_cost_to_complete, 0) AS estimate_at_completion,
  (b.original_budget + COALESCE(c.approved_co_budget, 0))
    - (COALESCE(a.cost_to_date, 0) + COALESCE(f.estimated_cost_to_complete, 0)) AS job_cost_variance
FROM jobs j
JOIN budget b       ON b.job_id = j.job_id
LEFT JOIN cos c     ON c.job_id = b.job_id AND c.cost_code = b.cost_code
LEFT JOIN actuals a ON a.job_id = b.job_id AND a.cost_code = b.cost_code
LEFT JOIN ctc f     ON f.job_id = b.job_id AND f.cost_code = b.cost_code
WHERE j.status = 'open';
-- Note: cost codes with actuals but no budget line need a FULL OUTER JOIN in production.

As a dashboard card

  • Card type: table with conditional formatting (jobs as rows; revised budget, EAC, variance $, variance %), plus a drill-down bar chart by cost code.
  • Measures: revised_budget, estimate_at_completion, job_cost_variance, job_cost_variance_pct, all defined once.
  • Dimensions: job, PM, division, cost code, cost type, period.
  • Default view: open jobs, current period, sorted by largest negative variance.
  • Per-tenant settings: sign convention, whether pending change orders are included, fiscal calendar. One contractor's controller may want pending COs shown as a separate column; another excludes them. Same governed definition, different saved view.
  • Ask it: "Which jobs went further over budget since last month?" compares the same measure across two periods.

Common mistakes

  • Comparing actual cost to date against the full budget on a job that is half done. That is not a variance; it is a progress number.
  • Forgetting approved change orders, which makes every job with extra scope look over budget.
  • Mixing committed cost (POs, subcontracts) into cost to date. Show committed separately.
  • Letting PMs leave cost-to-complete stale. A stale forecast hides overruns.

Version 1.0 · Last reviewed 2026-10-20 · Machine-readable definition