The worst conversation in construction bookkeeping happens at closeout. The job is done, the last invoice went out, and somebody finally adds it all up. A job everyone was pleased with turns out to have made almost nothing. Sometimes less than nothing.
Nobody was lying. The reports said it was fine. The reports were built on the wrong numbers, and they had been wrong since about week three.
What actually breaks construction job costing
Three things, and they compound in that order: costs coded to the wrong job, a WIP schedule built on those wrong costs, and retainage recorded as though it were ordinary revenue. Each one is survivable alone. Together they produce books that look perfectly tidy while the job performance underneath them is invisible.
QuickBooks Online can handle all three correctly. It will also handle all three wrongly without ever complaining, and that is the part worth understanding. Every failure below produces a file that reconciles to the penny. The bank matches. The P&L balances. Nothing turns red. The software is not going to be the thing that tells you.
Job costing: the crew and the bookkeeper are using different names
This is the least glamorous failure on the list and it causes the most damage.
Your foreman calls it the Henderson job. The invoice says Henderson Residence, Phase II. The bookkeeper opens a job called Henderson, then a second one called Henderson II three weeks later because a bill arrived that did not match anything. Now labour is landing in one, materials in another, and the change order is sitting in neither.
Nothing there is a mistake anyone would notice. Payroll still runs. The bank still reconciles. But the job-level report, the only one that tells you whether the work is making money, is quietly built from three piles that should have been one.
The rule is unglamorous and absolute: one job, one name, everywhere. The field, the invoices, the payroll allocation and the books all use the same identifier. If that is not true, everything downstream is decoration.
Where QuickBooks Online specifically lets it happen
QuickBooks Online has no object called a job. It has sub-customers, and job costing is a convention built on top of them rather than a feature you switch on. Four places it comes apart:
- The sub-customer is created twice. Nothing stops you. Two sub-customers under the same parent with near-identical names are the fingerprint, and the report that would show you sorts them alphabetically so they sit next to each other looking like one entry.
- "Bill with parent" is left on. Costs roll up to the customer and stop being attributable to the job. The customer total is right and every job under it is wrong.
- Costs are coded to an account instead of a product or service item. Accounts drive the P&L. Items drive job costing. Code a lumber bill to an expense account with no item and it lands in your financials correctly and in your job-cost report not at all.
- Labour is not allocated. Payroll posts to one overhead bucket instead of by job. This is the single most common cause of a job that looked fine, because labour is usually the largest cost on it.
None of these announce themselves. That is the through line of this whole article.
WIP: a schedule is only as honest as what feeds it
A work-in-progress schedule does two comparisons. It sets your actual costs against your estimated costs, and your billings against your percentage of completion. Done properly it tells you, mid-job, whether you are over-billed or under-billed and whether the estimate is holding.
Done on bad job-cost data it becomes a confident-looking document that is simply wrong. That is worse than not having one, because you will make decisions from it: whether to take the next job, whether to add a crew, whether you can afford the truck.
The tell is that everything looks calm. Payroll runs, costs land somewhere, the totals are right at company level. It is only at job level that the picture falls apart, and job level is the only level that matters when you are deciding what to bid next.
There is a check you can run without a formula, and it is better than the formula. Take a job you know well and stand on the site in your head. Would you say it is 60% done? Now open the schedule. If it says 85%, the inputs are wrong, and you do not need to reconcile anything to know that. Your own eyes are a control. Use them every time.
Retainage: the part almost everyone gets wrong
This is the one worth the whole article.
Retainage is money you have earned but not yet collected, held back until the job closes. It is easy to ignore precisely because it is coming later. And it gets recorded wrong in three distinct ways:
- Booked as if the full invoice were collected. Then the payment arrives short and nobody can explain the difference. This produces months of small unexplained variances that get "fixed" with adjusting entries.
- Never recorded as a retainage receivable at all. The money is simply not on your balance sheet. You are understating your own assets, and if you are borrowing against them, that has consequences beyond the books.
- Accidentally expensed. Money you earned, treated as money you spent.
The fix is specific enough to hand to whoever keeps your books. Retainage receivable belongs in its own asset account, never inside ordinary Accounts Receivable. Separate account, aged separately from your regular invoices, because it does not behave like a regular invoice. A 90-day A/R balance means somebody has not paid you. A 90-day retainage balance means the job has not closed. Those are different problems and they need different phone calls.
If you are a general contractor you are usually carrying both sides at once: retainage receivable from the owner, and retainage payable to your subs. Both are current liabilities and assets respectively even when the money will not move for more than a year. Netting them against each other hides both, and the two rarely release on the same day.
Buried inside ordinary receivables, retainage stops being visible as a category, and then you cannot answer the question that matters: how much have I earned that clients are still holding, and on which jobs? On a contractor running several jobs at once, that number is frequently the difference between comfortable and tight.
Why this keeps happening
Not incompetence. Most bookkeepers are good at bookkeeping. Construction is not general bookkeeping. It has its own vocabulary, and a bookkeeper who has never worked a job does not know what to ask for.
They will not ask why the change order has not been coded. They will not notice that a draw schedule does not line up with percentage of completion. They will not flag that retainage has quietly grown to a number you would want to know about. None of that is on a standard monthly close checklist, because on most businesses it does not exist.
It is the reason we have a general contractor on our team. Not as a credential to put on a page. Because when we ask you about a job, you are not going to be explaining what retainage is first.
The same gap shows up in every trade with its own vocabulary. Marketing agencies lose it through pass-through media and prepaid retainers rather than retainage, and for the same reason: a standard monthly close was not built to look for it.
Four things to check this week
- Pull a job-cost report and look for duplicate jobs. Near-identical names are the fingerprint. If you find them, the problem is upstream of the books.
- Find your retainage. If you cannot say what you are owed in retainage across open jobs in under a minute, it is not tracked as its own line.
- Compare one WIP line to reality. Take the job you know best. Does the percentage of completion match what you would say standing on the site?
- Check whether labour is allocated or lumped. Open one payroll run and see whether the hours carry a job on them. If they do not, your largest cost is invisible at job level.
Common questions
Can't I just run on cash basis and keep it simple?
You can, and plenty of smaller contractors do. The trade-off is that cash basis tells you what moved through the bank, not what a job earned. A month where you collected a big draw looks fantastic and a month where you paid for materials looks terrible, regardless of how the work is actually performing. It also makes a WIP schedule impossible, which matters the moment a bank or a bonding company asks for one.
At what size do I actually need WIP reporting?
Less about revenue than about overlap and duration. If you run several jobs at once, or jobs that span months and get billed in draws, you need it. That is exactly the situation where company-level numbers hide job-level problems. A single-job-at-a-time contractor can often get by without one.
My books are a mess mid-year. Is it too late to fix this year?
No, and mid-year is a much better time than after year-end. Reconstructing job costs is easier while the crew still remembers the work and the paperwork is findable. Waiting until a tax deadline means doing the same job under time pressure, which costs more and produces a worse result. That is a catch-up engagement rather than a monthly one.
Does construction accounting software solve it?
Partly. Good software makes correct job costing possible. It does not make it happen. If the field and the office still name jobs differently, or costs get coded at the end of the month from memory, the software faithfully records the wrong thing. The process has to be right first, and then the software is genuinely useful.
The place it usually breaks is the join. Most contractors end up running a field or project system alongside their accounting system, and the two were never properly connected. Jobs get created twice under different names, costs land in one and not the other, and someone re-keys the difference every month. That is the duplicate-job problem from earlier, arriving through the software rather than despite it.
Can you set the systems up so they actually talk to each other?
Yes, and we treat it as its own engagement rather than folding it into monthly work. We work with ServiceTitan and its QuickBooks integration, both the Online and Desktop paths, and getting that mapping right once is what makes the monthly bookkeeping cheap and accurate afterwards.
It is usually worth doing before the bookkeeping rather than after. Cleaning up a year of records and then connecting the systems means the cleanup has to be repeated. Connecting first means the cleanup only happens once. If you already run something and it is not feeding your books properly, that is a specific, finite project with an end date, not an open-ended retainer.
My ServiceTitan revenue doesn't match my P&L. What causes that?
Almost always the GL mapping between the two systems, and almost never anything dramatic. The usual culprits are unglamorous:
- Sub-accounts. An account set up as a sub-account in QuickBooks but not in ServiceTitan. ServiceTitan needs the full Parent Account:Sub-account Name format or the export fails to land where you expect.
- Names that don't match exactly. A difference in spacing or capitalisation is enough. So is a special character sitting in an account name on either side.
- An account type mismatch. The same account classified as a liability in QuickBooks and an asset in ServiceTitan.
- An account made inactive in QuickBooks while ServiceTitan is still mapped to it.
- Someone reorganised the chart of accounts. An income account renamed, or class tracking turned on or off, and ServiceTitan still pointed at the old structure.
None of these announce themselves. Transactions still export, the sync still reports success, and the totals quietly stop agreeing. If your revenue in one system has never quite matched the other and everyone has learned to live with a "known difference," that difference has a specific cause and it is findable.
Do I have to use percentage of completion for tax?
Usually yes on long-term contracts, with real exceptions that are worth knowing about. Small contractors under the gross-receipts threshold, and home-construction contracts, can use completed contract instead. The threshold moves with inflation and the answer turns on your average receipts over the prior three years, so it is worth checking against your actual numbers rather than assuming which side you fall on. Getting this wrong changes the year your income is taxed, not the amount, which is exactly the kind of error that is expensive and quiet. It also moves what you should be paying in during the year, which is a separate calculation with its own deadlines.
When it's worth a conversation
If you run one job at a time and read your own numbers, you probably do not need us. If you are running several jobs, billing in draws, carrying retainage across multiple clients, or you have had the closeout surprise more than once, that is a books problem, and it is fixable.
We would rather find it in week three than at closeout.
Closeout is where construction bookkeeping finally tells you the truth. It is also the one moment when nothing can be done about it. So go and pull the job-cost report. Find the duplicate name. Find the retainage. The job is still running.
Send us a job-cost report and your last WIP schedule. A general contractor and an Enrolled Agent will both read them, and we will tell you honestly whether you need a cleanup, a catch-up, or just a better monthly process.
See how we do bookkeeping
