
Revenue recognition general ledger integration is the mechanism that turns a signed contract into posted journal entries: performance obligations produce a schedule, the schedule produces periodic journals, and those journals post to deferred revenue, unbilled AR and top-line accounts in the GL. Done properly, the subledger reconciles to the trial balance every month without manual top-side adjustments.
The drift is almost always structural, not careless. The schedule lives somewhere the ledger cannot see — a spreadsheet maintained by one person, or a billing system that exports a single summarised journal each month. The GL receives a number. It does not receive the contract-level detail behind that number.
The symptoms are recognisable.
The account has a balance. Reconstructing which customers make it up takes a day of spreadsheet work.
Contract assets accumulate because the reclassification to receivables when invoicing happens is manual and occasionally skipped.
The subledger says one thing, the GL says another, and a plug entry closes the gap.
Prior-period figures change because someone amended a schedule retrospectively and re-exported.
ASC 606, and its IFRS equivalent adopted in Australia as AASB 15, provide the model that generates the schedule: identify the contract, identify performance obligations, determine the transaction price, allocate that price to obligations, and recognise it as each obligation is satisfied. That framework is well documented elsewhere — the FASB revenue recognition page and the AASB 15 standard are the primary sources. This guide assumes you know the model and deals with what happens after it: getting the resulting numbers into the ledger cleanly, and proving they tie.
Trace a single contract. A SaaS customer signs a 12-month agreement: an annual platform subscription, a one-off implementation engagement, and a bundled training allocation. That is potentially three performance obligations. The transaction price — the total consideration, adjusted for any variable elements — is allocated across them, typically on relative standalone selling price.
Each obligation then gets its own pattern of release.
That produces a revenue recognition schedule: a period-by-period expectation of how much revenue each obligation releases.
Separately, and independently, there is a billing schedule. The customer may pay annually upfront, quarterly in advance, or monthly in arrears. Implementation might be invoiced on milestones.
These two schedules are unrelated to each other, and that is the entire source of deferred revenue and unbilled AR. Bill ahead of delivery and you create a contract liability. Deliver ahead of billing and you create a contract asset. The GL accounts exist purely to hold the timing difference between two schedules that were never designed to match.
The practical consequence: the contract has to be held as structured data, not prose in a PDF and a formula in a spreadsheet. In Campfire, that lives in the Revenue module — Contracts, Customers, Revenue Transactions and the Revenue Dashboard — with Contract Templates in settings for standard commercial shapes. The point is not the product; the point is that the schedule needs to be a queryable object the ledger can post from and an auditor can drill into.
Below is the full entry set. All figures are illustrative examples for a hypothetical $12,000 annual subscription billed upfront, plus a $6,000 implementation.
Example journal entries across invoicing, revenue recognition, collections, implementation work and billing adjustments.
| # | Event | Debit | Credit | Amount (illustrative) | Effect |
|---|---|---|---|---|---|
| 1 | Invoice raised before delivery | Accounts Receivable | Deferred Revenue | 12,000 | Balance sheet only |
| 2 | Monthly revenue recognised | Deferred Revenue | Subscription Revenue | 1,000 | BS → P&L |
| 3 | Cash received | Cash | Accounts Receivable | 12,000 | Balance sheet only |
| 4 | Implementation delivered, not yet invoiced | Unbilled AR (contract asset) | Services Revenue | 6,000 | BS → P&L |
| 5 | Implementation invoiced | Accounts Receivable | Unbilled AR | 6,000 | Balance sheet reclass |
| 6 | Discount / concession granted | Contra Revenue | Accounts Receivable | 500 | Reduces net revenue |
| 7 | Credit memo issued (service credit) | Contra Revenue or Deferred Revenue | Accounts Receivable | 750 | Depends on whether revenue was recognised |
| 8 | Debit memo issued (under-billing correction) | Accounts Receivable | Deferred Revenue / Revenue | 400 | Depends on delivery status |
A few things worth being precise about.
Entry 1 creates no revenue. Invoicing is a billing event. It moves nothing through the income statement. Teams that treat invoice issuance as the recognition trigger are, functionally, running cash-basis accounting with extra steps.
Entry 4 is the one most often missed. Recognising income ahead of the right to invoice creates a contract asset, and that asset is conditional — it converts to a receivable only when the right to consideration becomes unconditional. If nobody owns the reclassification in entry 5, unbilled AR grows permanently and the balance sheet misstates both lines.
Credit memos need a decision, not a default. If the credit relates to revenue already recognised, it is contra revenue. If it relates to a billing not yet recognised, it reduces the deferred balance and never touches the P&L. Booking every credit memo to contra revenue overstates both the gross line and the offset.
Contra revenue should be a distinct account, not netted against the gross line at source. Discounts, refunds and concessions are analytically different from a lower price, and investors reviewing SaaS metrics will ask for the gross-to-net bridge.
Mid-term upgrades are where schedules break. The treatment depends on whether the modification adds a distinct good or service at its standalone price (account for it as a separate contract), or changes the existing arrangement (either terminate-and-replace prospectively, or adjust cumulatively).
The mechanics in the ledger:
Every step here is a judgement call, and every one should leave a documented trail. Campfire holds these as Invoices, Credit Memos, Debit Memos and Journal Entries — discrete objects rather than lines buried in a workbook.
A chart of accounts that supports 606/15 reporting needs, at minimum:
The instinct when someone asks for a breakdown by product line, region or team is to add accounts. Resist it. A chart of accounts that grows to hundreds of revenue codes becomes unmaintainable and makes consolidated reporting worse, not better.
Dimension the postings instead. In Campfire that means Departments, Entities and Tags (with Tag Groups) applied at the transaction level, so the top line can be sliced by any combination without touching the account structure. Products & Services and Product Bundles carry the mapping from what was sold to where it posts.
Venture-backed SaaS companies acquire entities faster than they acquire finance headcount. Three considerations.
Which legal entity holds the contract determines where income and the related contract balances sit. Configure Entities before the first contract is loaded, not after.
Where one entity contracts with the customer and another delivers, the recharge needs its own journals and must eliminate on consolidation. Campfire's Intercompany Journals exist for this.
A contract billed in a non-functional currency needs a defined policy on which rate applies to the recognition entry versus the receivable revaluation. Deferred revenue is generally a non-monetary balance and is not retranslated; the receivable is. Set this in Foreign Exchange Rates and document the policy — it is a recurring audit question.
The classic trade-off: one summarised journal per period, or a posting per transaction.
| Summary posting | Transaction-level posting | |
|---|---|---|
| GL volume | Low | High |
| Drill-down from P&L to contract | Requires external workbook | Native |
| Reconciliation | Subledger-to-GL tie-out required | Tie is structural |
| Dispute / audit sampling | Manual retrieval | Direct |
| Dimension richness | Lost or approximated | Preserved per transaction |
| Restating one contract | Re-export whole journal | Amend one transaction |
Summary posting made sense when the ledger was a constrained resource. On a modern platform it mostly buys a reconciliation problem: the subledger and the GL become two versions of the truth, and the monthly tie-out is work that exists only because of the posting choice.
Post at transaction level where the platform supports it, and rely on drill-down reporting for readability. The income statement still shows a single line; clicking it should reach the contract.
Three controls matter regardless of granularity.
Distinguish posting date from service period. A December service period accrued in a January-dated journal is a cut-off error waiting to be found. Recognition should key off the service period.
Once a period is signed off, lock it. Retrospective edits to closed months are the single most common cause of comparatives that move between board packs.
Predictable, unchanging schedules — a fixed ratable release, a standing accrual — belong in Recurring Journal Entries rather than being rekeyed monthly.
The close routine that proves integration is working:
1. Deferred revenue rollforward.
Opening deferred revenue
+ New billings deferred
– Revenue recognised from deferred
± Modifications, credits, FX
= Closing deferred revenue
Closing balance must agree to the trial balance to the cent, and the total must agree to the sum of contract-level unrecognised balances. Two independent proofs, same number.
2. Age and clear unbilled AR. Produce an ageing of contract assets. Anything past its expected invoice date is either a missed invoice or a recognition error. There is no third explanation.
3. Agree revenue to the subledger. It should reconcile to the Revenue Transactions total by category. Investigate every variance; do not net them.
4. Review contra revenue. Check that credits were routed correctly between the contra and deferred accounts, and that the gross-to-net bridge is explainable.
5. Flux analysis. Movement in the top line and deferred balances versus prior period and budget, with a written explanation for each material variance. Flux analysis is where the reconciliation stops being arithmetic and starts being review.
6. Sign-off. A Close Checklist with named owners per task, plus an Audit Log capturing who posted, amended and approved what. Auditors will ask for both.
Bank Reconciliation, Accruals and Trial Balance complete the picture — the cash side has to agree before the receivables ageing means anything.
Automation belongs where the rule is deterministic. Judgement belongs where it is not.
Automate:
Keep human:
Ember AI, Campfire's built-in AI teammate, groups transactions and suggests actions — useful for surfacing what needs attention in a high-volume ledger. Suggestion is the operative word: the approval and validation layers remain the control, and a suggested action is still an action a person accepts.
Migrating revenue is harder than migrating the GL, because you are migrating in-flight state, not just balances. Prepare.
Deferred revenue and unbilled AR broken down to contract and performance obligation level — not just the account balance. This is usually the longest task.
Each needs its remaining schedule reconstructed in the new system so future periods recognise correctly.
Decide how many periods to load. Board and audit requirements drive this.
Migration is the only cheap moment to split deferred revenue by term, separate contract assets and introduce dimensions.
Lock everything prior in the legacy system. Xero and QuickBooks both support period locking; use it.
One or two closes run in both systems, with a documented variance analysis. Non-negotiable for anything audited.
Bank feeds and system connections configured and tested before cut-over, not during.
Cynder's Implementation service covers migration, configuration and rollout for finance teams moving off Xero or QuickBooks onto Campfire — including the chart of accounts work and the parallel close.
If your deferred revenue rollforward currently starts with "open last month's workbook," that is the constraint worth removing before your next audit.
Deferred revenue (a contract liability) arises when you invoice or collect before delivering — you owe the customer performance. Unbilled AR (a contract asset) arises when you deliver before you have an unconditional right to invoice — the customer owes you, but the invoice hasn't been raised. They are opposite sides of the same timing gap between billing and recognition, and both should sit in separate GL accounts.
Transaction level, where your platform supports it. Summary posting keeps GL volume low but creates a permanent reconciliation gap between subledger and ledger, loses transaction-level dimensions, and forces manual retrieval for audit sampling or customer disputes. Detail postings with drill-down reporting give the same readable income statement while making the subledger-to-GL tie structural rather than a monthly exercise.
Run a deferred revenue rollforward (opening + billings − amounts recognised ± adjustments = closing) and agree the closing balance to both the trial balance and the sum of contract-level unrecognised balances. Then agree income statement revenue by category to subledger totals, age and clear unbilled AR, review contra-revenue routing, and complete flux analysis with written explanations for material movements.
First determine the treatment: a distinct addition at standalone price is a separate contract; otherwise apply prospective or cumulative-catch-up treatment. Then close the original schedule at the modification date, recalculate the remaining transaction price, reallocate across remaining performance obligations, and generate a forward schedule. Post a cumulative catch-up journal only where the modification requires it. Document the judgement — auditors test modifications.