Ryan Ginsberg

September 2, 2026 · 9 min read

A co-termed upsell is two line items, and only one of them is recurring

Someone in a HubSpot practitioner room asked how to model a mid-contract upsell without Contracts or Revenue Hub. The answer is short. The reason it matters is the two dates nobody is checking.

This started as a question in a HubSpot practitioner community. A company had moved to annual pricing, had customers buying extra things mid-contract, and wanted those add-ons to end on the same date as the original agreement. They were not using Quotes, Contracts or Revenue Hub, HubSpot was not running their billing, and what they wanted from it was honest reporting: the upsell, the ARR, the contract value, and a renewal date they could trust. I have written the answer up here because the model is simple and the reasoning behind it is the part that usually gets skipped.

Two words first

Co-term
Lining up something new so it ends on the same date as a contract the customer already has. One renewal date for everything, instead of a new one every time they buy. Signed in January for twelve months, buys an add-on in April: co-terming makes the add-on end in December too, and December is the co-term date.
Stub
The short, odd-length period between when the add-on starts and the co-term date. April to December is a nine-month stub. It is a partial term rather than a full one, it only happens once, and after it everything renews together on a normal cycle.

What the customer is actually buying

Take Product A at 12,000 a year, sold to a customer with nine months left. Commercially they are buying two things, and the reason the modelling gets awkward is that people try to make one line item carry both. The first thing is nine months of Product A, billed once, now. The second is Product A on a full annual term, starting on the co-term date and renewing with everything else. The stub ends exactly where the ongoing commitment begins, which is why the annual line's billing start date is the same date as the original renewal.

The instinct that gets people into trouble is to put a nine-month term on an annual-frequency line, and when HubSpot's product configuration refuses that, to reach for a monthly-frequency line at the annual price divided by twelve instead. HubSpot accepts every field on that second version, which is what makes it look like the answer.

Two ways to model the stub, and what the deal reports

Rather than guess, I pulled the calculation formulas HubSpot defines on the line item object for ARR, MRR and total contract value. They are HubSpot-defined, so they are identical in every portal. On a monthly-frequency line, MRR is the unit price and ARR is the unit price times the term in months, capped at twelve. On an annual line, ARR is the unit price divided by twelve times the term, capped the same way. A line with no billing frequency at all contributes zero to both and its full amount to contract value. Contract value on any line is amount times number of payments.

Stub as a monthly lineARRMRRTCV
Annual line, 12,000 annually, 12 months12,0001,00012,000
Stub, 1,000 monthly, 9-month term9,0001,0009,000
Deal rollup21,0002,00021,000
The deal reports 21,000 ARR and 2,000 MRR for a customer paying 12,000 a year. The stub is counted as recurring because its frequency says it is.
Stub as a one-time lineARRMRRTCV
Annual line, 12,000 annually, 12 months12,0001,00012,000
Stub, 9,000 once, no frequency009,000
Deal rollup12,0001,00021,000
ARR is the ongoing commitment. Contract value is everything the customer owes. The upsell is visible as the one-time line plus the change in ARR.

So the monthly version does not break anything HubSpot will tell you about. It breaks the two numbers the company said it wanted to trust, and it does so quietly, because every field validates. Contract value is right under both, which is part of why the problem survives: the report someone checks first looks fine.

How each line is configured

FieldLine 1, the stubLine 2, the ongoing commitment
ProductProduct A co-term, a companion one-time product with unit price = annual ÷ 12Product A
Unit price1,00012,000
Quantity9, the months remaining1
Billing frequencyempty, one-timeAnnually
Termempty12 months
Billing start dateempty, bills on closethe co-term date
Delayed billing startemptyempty, never alongside a start date
Prorateoff, the quantity already does itoff
What it computesARR 0, MRR 0, TCV 9,000ARR 12,000, MRR 1,000, TCV 12,000, end date = start + 12 months
Quantity nine at the monthly rate keeps the arithmetic visible on the record and lets a workflow derive it from the co-term date. Quantity one at 9,000 computes the same three numbers if you would rather see the total.

One thing to check in your own portal

Whether your line items are getting a term at all. A line with a frequency and no term computes as twelve months, which happens to be right here, but it is worth knowing rather than assuming. And setting a billing start date and a delayed start on the same line makes the start-terms property compute to nothing, with no warning. A line that has a start date and a blank start-terms property has been double-set.

Where every date lives, and who puts it there

This is the part I would actually spend the hour on. Seven dates and quantities touch a co-termed upsell. Five of them can be computed or copied by the system. Two of them are typed by a person into a field that has no view of the deal behind it, and nothing checks them.

The dateWhere it is storedWho writes itWhere the rep sees it
Original renewal dateOriginal deal, the renewal property you already haveTyped once, at the original closeThe original deal record
Contract end date on the customerCompany, a custom date propertyWorkflow, copied up from the deal that closed wonThe company record, visible from any deal. One date per customer
Co-term date on the upsellUpsell deal, a custom date propertyWorkflow, copied from the associated company when the deal is createdThe deal's own properties. Make it required before the stage where lines are added
Months remainingUpsell deal, a calculated time-between propertyComputed from close date and co-term dateRead-only on the deal, beside the co-term date
Stub quantityLine 1, quantityTyped by the repThe line item editor. Nothing checks it against months remaining
Annual line billing startLine 2, billing start dateTyped by the repThe line item editor, under billing terms. Nothing checks it against the deal
Next renewal dateLine 2, billing end date, calculatedComputed as start plus termOn the line item. Roll it to the deal and the company so the next upsell starts from it
The line item editor is a modal with no view of the deal. The date the rep needs is on the deal, and the field they type it into cannot see it. That is the whole problem in one sentence.

What enforces the two manual entries

There are three levels, and each removes a piece of the manual process. Only the last removes the person from the date arithmetic entirely, and it is worth being clear-eyed about which one you are buying.

Level one, native, this week

Make the co-term date required on the deal before the line-item stage, so a deal cannot carry lines without one. Calculate months remaining on the deal and show it beside the co-term date, so the rep reads the stub quantity off the record rather than working it out. Build a saved view of line items on open upsell deals with billing start date next to the deal's co-term date, so a mismatch is visible in one glance. None of that stops a wrong entry. It puts the right answer in front of the person at the moment they type, which is more than most portals do, and in my experience it is most of the damage.

Level two, custom code

When a line item is associated to an upsell deal, a custom code action reads the deal's co-term date and months remaining and writes the stub quantity and the annual line's billing start date itself, then re-checks on every edit and flags a deal whose lines disagree with its date. That needs Operations Hub Professional, or line item workflows if your portal has them, which I have not verified for every tier. It is what a system enforcing the date looks like without Contracts. Someone owns the code, and the co-term date is still a property a person could overwrite.

Level three, Contracts

The contract holds the end date, and there is no copy on the company or the deal to drift. The upsell is a change on the contract, and the system prorates it to the contract's end date, so nobody types nine and nobody types a start date. The renewal quote inherits the contract's dates. What you take on instead is a beta surface, and HubSpot holding the agreement of record alongside whatever holds the signed document today.

Without Contracts, with Contracts

So, to the question I was actually asked: no, the Contract object is not essential for the reporting, and I would not bring Contracts or Revenue Hub in to solve a reporting problem when HubSpot is not running the billing. The line items are the same shape either way. What changes is which object holds the agreement and who does the date arithmetic.

Without ContractsWith Contracts (Revenue Hub, beta as of September 2026)
The agreementNo record of its own. Implied by the original deal plus its close date and term, with the signed document wherever you keep itA Contract record with an effective date, a term and an end date
Where the co-term date livesOn the original deal, copied to the Company by workflow. A customer with several live agreements keeps it on the original deal and links upsells with a deal-to-deal associationThe contract's end date. Nothing to copy
The two linesOne-time stub at the prorated amount plus an annual line starting on the co-term dateThe same two lines, added to the contract by the amendment
ARR, MRR, TCV12,000, 1,000, 21,000 from the line item formulasSame numbers, same formulas, rolled to the contract as well as the deal
The next renewal dateComputed on the annual line as start plus termHeld on the contract and inherited by the renewal quote
Mid-term change historyEach upsell is its own deal. What changed since signing is a list of deals against the companyEach change is recorded on the contract and mints an order carrying only the delta lines
Billing scheduleNot in HubSpot, which is the situation todayGenerated from the contract's lines, if you want HubSpot to own it
What you give upOne date per company. Change history reconstructed from deals. Two entries a person typesA beta surface. The changes endpoint moved once in August 2026 without notice

Build the two lines now, put the date somewhere a new deal can reach, and moving to Contracts later is a migration of the agreement record rather than of the line items. If you spend a year with co-term dates that exist only implicitly in deal history and then move, you are reconstructing every agreement's term from a chain of deals, and that is very cheap to avoid today.

The formulas above were read from the line item property schema on 2 September 2026. The Contracts column describes the model as HubSpot has published it and as I have seen it behave; I did not test it against a live portal for this piece, and given how recently it moved I would re-read it before building on it.

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.