What it is
Contractors bill customers on a schedule, often monthly progress billings. Revenue, though, is earned as the work is done. The two rarely match.
Over/under billing measures the gap, job by job. It is the core of the work in progress (WIP) schedule, the monthly report that controllers prepare and that sureties and lenders review.
Why operators track it
- Cash. Underbilling usually means work has been done but not invoiced, so cash is tied up.
- Risk. Underbilling can also mean costs are running ahead of plan on a job that is in trouble. Large overbilling on a job with a shrinking margin can mean cash collected now will be needed to finish the work.
- Bonding and credit. Sureties and lenders look at the WIP schedule when deciding bonding capacity and credit lines.
- Accurate revenue. Earned revenue drives the income statement for companies that recognize revenue over time.
How it is calculated
Over/under billing = billed to date − earned revenue
- Earned revenue = percent complete × revised contract value
- Percent complete (cost-to-cost method) = cost to date ÷ estimated total cost
- Estimated total cost = cost to date + estimated cost to complete
Revenue recognition rules (ASC 606 for US GAAP) govern how a company recognizes revenue over time. Cost-to-cost is a common input method. Confirm the method with a CPA; this page explains the calculation, not the accounting policy.
Worked example
Job 2417 has a revised contract value of $1,500,000. Cost to date is $910,000 and estimated total cost is $1,330,000, so the job is 68.4% complete and has earned $1,026,316. The contractor has billed $1,100,000.
How to read it
- Positive is overbilled (billed ahead of the work). It is recorded as a liability, often labeled "billings in excess of costs and estimated earnings".
- Negative is underbilled (work done, not yet billed). It is recorded as an asset, often labeled "costs and estimated earnings in excess of billings".
- Neither is good or bad by itself. Moderate overbilling helps cash flow. What matters is whether each balance can be explained.
- Watch the combination with margin. A job that is underbilled and has a fading projected margin deserves a closer look.
- There is no universal target, so we do not publish a benchmark.
Definitional choices and common pitfalls
- Percent complete method. Cost-to-cost is common. Some companies use units installed or engineer estimates for certain job types.
- Retainage. Billed to date normally includes retainage billed, even if it has not been collected. Some reports show retainage separately.
- Change orders. Use the revised contract value once change orders are approved. Label any unapproved change orders that are included.
- Do not net the two sides. Overbillings and underbillings go to different balance sheet lines. Report both totals.
- Stale cost to complete. Because percent complete depends on estimated total cost, an outdated forecast distorts earned revenue.
How different roles use it
| Role | How they use it |
|---|---|
| Owner / CEO | Watches total underbilling as a cash signal and asks about any large balance. |
| CFO / controller | Prepares the WIP schedule monthly, ties it to the financial statements, and sends it to the surety and lender. |
| Project manager | Explains the balance on their jobs and makes sure billing keeps pace with work done. |
| Surety / lender | Reviews the schedule when setting bonding capacity and credit. |
Questions it answers
- Which jobs are billed behind the work?
- How much cash is tied up in underbilling?
- Are any overbilled jobs also losing margin?
- Is the WIP schedule ready for the surety?
How to present it in a report
- Use the standard WIP schedule layout: one row per open job with contract value, cost to date, estimated total cost, percent complete, earned revenue, billed to date, and over/under.
- Show total overbilled and total underbilled separately at the top.
- Add projected margin and its change since last month so readers can spot fade.
- Produce the same layout every month. Sureties and lenders compare period to period.
Data you need
Fields
| Field | What it means | Example value |
|---|---|---|
| Job | The project, with its PM and division | Job 2417 |
| Original contract value | Contract amount at award | $1,400,000 |
| Approved change order revenue | Contract value added by approved change orders | $100,000 |
| Cost to date | All posted job cost | $910,000 |
| Estimated cost to complete | The PM's forecast of remaining cost | $420,000 |
| Billed to date | Total progress billings, including retainage billed | $1,100,000 |
| Retainage billed | Share of billings held back by the owner | $110,000 |
What the raw data looks like
Example data A few rows as they might come out of the source system.
| Job | Contract | Approved CO revenue | Cost to date | Cost to complete | Billed to date | Retainage | Month end |
|---|---|---|---|---|---|---|---|
| 2417 | $1,400,000 | $100,000 | $910,000 | $420,000 | $1,100,000 | $110,000 | Oct 31 |
| 2420 | $860,000 | $0 | $240,000 | $470,000 | $205,000 | $20,500 | Oct 31 |
| 2431 | $2,150,000 | $35,000 | $1,620,000 | $310,000 | $1,700,000 | $170,000 | Oct 31 |
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 order revenue and cost entered separately. If only one side is entered, percent complete and earned revenue are both wrong.
- Billings without retainage split. Some systems store net billings only. Ask how retainage is recorded.
- Stale cost to complete. It changes percent complete, so earned revenue moves with it.
- Unposted costs at month end. Invoices not yet entered make the job look less complete and underbilled.
- Closed jobs still open. Jobs that are finished but not closed out in the system stay on the WIP schedule.
Related metrics
- Job cost variance: the EAC that drives percent complete.
- Gross margin by job: earned revenue minus cost to date.
- Backlog: revised contract value minus earned revenue.
- Retainage receivable: cash billed but held back. Coming soon.
FAQ
- Is overbilling good or bad?
- Neither by itself. Moderate overbilling helps cash flow. Large overbilling on a job with falling margin is a risk because the cash will be needed to finish the work.
- Why does underbilling worry lenders and sureties?
- It can mean unbilled work, or costs running ahead because the job is in trouble. It is an asset that has not turned into cash.
- What is the cost-to-cost method?
- Percent complete equals cost to date divided by estimated total cost. It is a common input method for recognizing revenue over time.
- How often should the WIP schedule be prepared?
- Monthly, after costs and billings for the month are posted and PMs have updated cost-to-complete.
For your data teamFormula variants, tables, SQL sketch, and dashboard spec
Formula details
Using the cost-to-cost method of percentage of completion:
revised_contract_value = original_contract + approved_change_orders (revenue side)
estimated_total_cost = cost_to_date + estimated_cost_to_complete
percent_complete = cost_to_date / estimated_total_cost
earned_revenue = percent_complete * revised_contract_value
over_under_billing = billed_to_date - earned_revenue
- Overbilled (positive): recorded as a liability, often labeled "billings in excess of costs and estimated earnings".
- Underbilled (negative): recorded as an asset, often labeled "costs and estimated earnings in excess of billings".
- Billed to date includes retainage billed, even if not yet collected.
Revenue recognition rules (ASC 606 for US GAAP) govern how a company recognizes revenue over time. Cost-to-cost is a common input method. Confirm the method with your CPA; this page explains the calculation, not the accounting policy.
Worked example detail
| Job 2417 | |
|---|---|
| Revised contract value | $1,500,000 |
| Cost to date | $910,000 |
| Estimated cost to complete | $420,000 |
| Estimated total cost | $1,330,000 |
| Percent complete | 910,000 / 1,330,000 = 68.4% |
| Earned revenue | 68.4% x 1,500,000 = $1,026,316 |
| Billed to date | $1,100,000 |
| Over/(under) billing | 1,100,000 - 1,026,316 = $73,684 overbilled |
Tables and fields
| Table | Fields | Notes |
|---|---|---|
jobs |
job_id, pm_id, division, original_contract, status | |
change_orders |
job_id, revenue_amount, budget_amount, status, approved_at | Revenue side and cost side |
job_costs |
job_id, amount, posted_at | All posted job cost |
cost_forecasts |
job_id, period, estimated_cost_to_complete | PM monthly forecast |
billings |
job_id, invoice_id, amount, retainage_amount, invoice_date | Progress billings (AIA G702/G703 or similar) |
SQL sketch
WITH contract AS (
SELECT j.job_id, j.pm_id, j.division,
j.original_contract + COALESCE(SUM(co.revenue_amount) FILTER (
WHERE co.status = 'approved' AND co.approved_at <= :as_of), 0) AS revised_contract_value
FROM jobs j LEFT JOIN change_orders co ON co.job_id = j.job_id
GROUP BY 1, 2, 3, j.original_contract
),
cost AS (
SELECT job_id, SUM(amount) AS cost_to_date
FROM job_costs WHERE posted_at <= :as_of GROUP BY 1
),
ctc AS (
SELECT job_id, SUM(estimated_cost_to_complete) AS cost_to_complete
FROM cost_forecasts WHERE period = :period GROUP BY 1
),
billed AS (
SELECT job_id, SUM(amount) AS billed_to_date -- gross, including retainage
FROM billings WHERE invoice_date <= :as_of GROUP BY 1
)
SELECT
c.job_id, c.pm_id, c.division,
c.revised_contract_value,
co.cost_to_date,
co.cost_to_date + COALESCE(t.cost_to_complete, 0) AS estimated_total_cost,
co.cost_to_date / NULLIF(co.cost_to_date + COALESCE(t.cost_to_complete,0), 0) AS percent_complete,
c.revised_contract_value * co.cost_to_date
/ NULLIF(co.cost_to_date + COALESCE(t.cost_to_complete,0), 0) AS earned_revenue,
COALESCE(b.billed_to_date, 0) AS billed_to_date,
COALESCE(b.billed_to_date, 0) - c.revised_contract_value * co.cost_to_date
/ NULLIF(co.cost_to_date + COALESCE(t.cost_to_complete,0), 0) AS over_under_billing
FROM contract c
JOIN cost co ON co.job_id = c.job_id
LEFT JOIN ctc t ON t.job_id = c.job_id
LEFT JOIN billed b ON b.job_id = c.job_id;
As a dashboard card
- Card type: WIP schedule table (one row per open job, columns as in the worked example), with a summary KPI pair: total overbilled and total underbilled. A diverging bar chart by job shows which side each job is on.
- Measures:
revised_contract_value,cost_to_date,estimated_total_cost,percent_complete,earned_revenue,billed_to_date,over_under_billing, all governed so the controller, the PM, and the surety package use identical numbers. - Dimensions: job, PM, division, period (month end).
- Default view: current month end, open jobs, sorted by absolute over/under billing.
- Per-tenant settings: fiscal year start, whether retainage is shown gross or net, percent complete method (cost-to-cost by default). Each contractor saves its own version; the earned revenue math stays governed.
- Export: scheduled monthly PDF or Excel to the controller and the surety contact.
Common mistakes
- Netting overbillings and underbillings into one company total. Report both sides; they go to different balance sheet lines.
- Using the original contract value after change orders are approved.
- Using a stale cost-to-complete, which makes percent complete (and earned revenue) wrong.
- Mixing in unapproved change orders without labeling them.