Ryan Ginsberg

September 5, 2026 · 5 min read

HubSpot built a guard, and it covers half the records

Every billing cycle on a subscription mints two new line items, one for the invoice and one for the payment. HubSpot deliberately zeroes the recurring-revenue fields on one side and leaves the other populated, so summing the protected property overstates worse than summing the one it never guarded.

The last piece traced the one hop that doesn't copy: a deal becomes an order and HubSpot reuses the same line item rather than minting a new one. That restraint doesn't carry into what happens next. The order becomes a subscription, the subscription starts billing, and every month it does, two more line item records get created. They're two separate records, not one shared between the invoice and the payment, and neither is the subscription's own record re-associated.

On the sale I've been tracing, one product at $9,995 a month on a six-month term, $59,970 owed across the contract, that's twelve new records over six billing cycles. Here's where they came from, and what HubSpot did to one side of them that it never did to the other.

Two new records, every billing cycle

Six billing periods ran on the traced sale, December 2025 through May 2026. Each produced an invoice, and each invoice arrived with a brand-new line item attached, not the subscription's line item re-associated and not the deal's, a fresh record with its own ID. Each period also produced a payment, and the payment got its own new line item too, a different record from the invoice's, even though they cover the identical month and the identical $9,995.

All twelve carry the same value in the property HubSpot's schema calls "how this record was created," hs_object_source_label: PAYMENTS. That's the commerce engine's own signature, distinct from the QUOTES source on the quote copy and the CRM_UI source on the deal-and-order record. The only way to tell one December record from the next, short of the ID, is a pair of hidden, read-only date fields, hs_billing_period_start_date and hs_billing_period_end_date, the start and end of the one month each record covers.

This isn't confined to one sale. Across the whole portal, 121 line items are parented to an invoice and 85 to a payment, and not one line item appears in both sets. The two populations are disjoint. Whatever an invoice's line item is, the payment for that same invoice doesn't reuse it.

The field HubSpot zeroed

Look at what each of the six invoice copies reads. amount, the field that holds a line item's dollar value, stays fully populated on every one at $9,995. But the property that holds Monthly Recurring Revenue, hs_mrr, reads $0.00 on all six, and so does hs_arr, Annual Recurring Revenue.

I read that as deliberate rather than a missing sync, and I think it's the right call, because HubSpot zeroes hs_mrr and hs_arr on the invoice-side copies so that whatever rolls up recurring revenue elsewhere in the system doesn't count a monthly invoice as if it were a monthly subscription. Six invoices from one subscription shouldn't read as six subscriptions' worth of MRR, and on this property, at this hop, HubSpot made sure they don't.

Billing periodInvoice line itemhs_mrrhs_arrPayment line itemhs_mrrhs_arr
Dec 202545874803266$0.00$0.0046032696170$9,995$59,970
Jan 202648171255893$0.00$0.0048195253295$9,995$59,970
Feb 202650532847543$0.00$0.0050520446795$9,995$59,970
Mar 202652548893565$0.00$0.0052550541469$9,995$59,970
Apr 202653828373362$0.00$0.0053823109435$9,995$59,970
May 202654979492673$0.00$0.0054963959068$9,995$59,970

The field it didn't

Read across the table. Every payment-side record in the right-hand columns carries the full $9,995 in hs_mrr and the full $59,970 in hs_arr, the same numbers the subscription's own line item carries. So HubSpot built a guard against exactly this shape of over-counting and didn't apply it to the other new record created in the same billing cycle. I don't know why, and I'd guess the payment record was built by a different team for a different purpose, but the effect is the same either way.

Add it up the way a report builder adds it up: sum hs_mrr with no filter across all fifteen records this sale produced. Nine carry a non-zero value, the quote copy, the shared deal-and-order record, the subscription copy, and all six payment copies. Nine at $9,995 is $89,955 a month, reported for a subscription that bills $9,995 a month. That's 9x. The first piece showed that summing amount across the same fifteen overstates by 2.5x. The property HubSpot built a specific defence for produces a worse number than the property it left alone.

The guard did its job, to be fair to it. Every invoice-side copy that could have polluted an hs_mrr rollup reads zero, as intended. It covers one property, on one side of one hop, in a chain that copies at every hop but one.

A key that reaches this far, at least once

The third piece introduced hs_origin_key, the hidden identifier HubSpot writes onto the parallel quote-side and deal-side copies so they can be traced back to each other. It isn't confined to that hop. Elsewhere in this portal, a $5,750 support-services line item parented to an invoice and a $5,750 line item parented to a payment, created in the same millisecond, carry the identical origin key.

That's a real signal the two copies are the same sold thing, and it reaches the invoice-and-payment hop. It just doesn't reach it reliably. No subscription-, order- or cart-parented line item in this portal carries an origin key at all, and the key only started populating on records created from October 2025. I wouldn't build a reconciliation on the assumption it's on every record it should be on.

What to check in your own portal

If an MRR report has ever been built by summing hs_mrr across the Line Item object instead of reading it off a subscription's or a deal's rollup property, this is the reason the number came out wrong, and now there's a way to say by how much. Pull a subscription with a few billing cycles behind it, filter its line items to the payment association only, and sum hs_mrr there. Compare that against the subscription's own rolled-up total, hs_total_mrr. The gap is the size of this exact problem in your portal, and it's checkable in an afternoon.

The subscription itself is the one container in this chain that can hold two states of the same line item at once, what it's charging today and what it's about to charge starting next month. That's the next piece.

More writing

Let's talk

You bet on HubSpot. It still isn't running your business.

That's the conversation I want — 30 minutes, no contract, no black box. Tell me what's actually broken and I'll tell you straight what I see. It's transcribed and shared back to you, so you keep a real read on where you stand and what I'd do first, whether or not we work together.

Not ready for a call? Email me your situation and I'll tell you straight whether you need me. No form, no sequence, nothing captured — if the honest answer is that you don't need me, that's the answer you'll get.