SaaS and technology · Base expansion

Expansion, upsell and repurchase timing

How much new revenue came from the base, which customers still don't have the module that makes sense and who is at the moment to buy again.

UsageSpecific
EffortMedium
ForSaaS companies with more than one module or plan, or with recurring sales to the same base, that want to grow revenue from current customers.
Source

Billing items, expansion deals and usage

Rule

Difference by customer and product, without migration

Outcome

Expansion, attach and repurchase queue

Activation

CS queue, forecast and AI agent

What it solves

  • Expansion separated from plan migration and billing-cycle changes.
  • For each module, who has it, who doesn't and who should.
  • A repurchase queue at the right time, based on each customer's cycle.

Business questions it answers

Ask your agent these questions once the case is live.

How much expansion MRR did we have this quarter, and in which products?
Which customers of the core product still don't use module X?
Which companies are at repurchase timing this month?
How much of this month's new revenue came from the base?
What is each module's attach rate by plan?
Which accounts have the most upsell potential for CS to work?

What you need

  • Billing with the items and products of each subscription or charge
  • Subscription history (daily snapshot or change events)
  • The CRM's expansion and CS pipelines and the list of segments that go into re-engagement

What you get

  • An MRR waterfall by customer and product, with upsell and cross-sell flagged
  • An attach matrix by module and plan
  • Upsell and repurchase queues by account owner
  • An AI agent that answers about expansion and who is ready to buy

Where to activate

CS and account management queue

Companies at repurchase timing and accounts with upsell potential, by owner, with the suggested module.

Expansion forecast

The CS expansion pipeline goes into projected month-end MRR, separate from new sales.

AI agent via MCP

Answers who doesn't have the module yet, who is at the moment to buy and how much the base expanded.

Ready to build?

If customer-level MRR already exists, the product lens is one step away. The repurchase queue depends on a clean per-company purchase history in the CRM. The detailed view has the business rules, the pitfalls and the acceptance test. Or send everything straight to your agent with the Nekt MCP.

The problem

Billing keeps the current state: when the customer increases quantity or adds a module on the same subscription, yesterday's snapshot is overwritten and the expansion disappears. When they cancel and re-sign to change plans, it shows up as churn and a new customer. And the upsell closed in the CRM goes into the new-business target. Nobody knows how much the base grew, or whom to offer the next module.

How it is usually done, and the rule

Each row is a mistake that already happened in practice.

The common wayThe rule
01
Summing the MRR of new items in the month, without comparing with last month.
Expansion is a difference by customer and product

Compute each customer's MRR by product at month end and compare it with the previous month end. An increase in a product the customer already had is upsell. MRR in a product the customer didn't have, while already paying, is cross-sell: expansion flagged as a new product. The product lens adds up to the customer lens, and both use the same month boundary.

02
Measuring expansion only from new subscriptions.
Capture changes inside the subscription

Quantity changes, price changes, items added or removed and discounts applied on the same subscription don't show in a table that keeps only current state. Use subscription change events or a daily snapshot of items. Events complement the snapshot, they don't replace it: new and canceled subscriptions still come from the snapshot, so nothing is counted twice.

03
Counting a cycle switch or a re-sign as upsell.
Migration is not expansion

Switching from monthly to annual, a cycle renewal and canceling and re-signing to change plans are migrations of the same customer. Separate natural expansion from migration in a column: migration moves MRR but isn't a sale to the base. A renewal with the same quantity and price is not a movement.

04
Accepting every billing expansion without checking for a charge.
Expansion without a charge is suspicious

On a monthly plan, expansion with no paid charge in the month points to an early setup or a wrong item: flag it for review. On an annual plan, expansion in a month without a charge is normal. Customers from channels that don't create invoices in billing (external checkout, store) trigger false alarms and stay out of this check.

05
Letting upsell come in as a new sale.
An upsell closed in the CRM is expansion

A won upsell deal counts as expansion in the forecast and in commissions, never toward the new-logo target. A deal in the new-business funnel for a company that is already a customer is misclassified expansion and goes to review.

06
Dividing by all customers, including those who can't buy it.
Module attach over the eligible base

Module attach rate = active customers with the module / active customers who can buy it (eligible plan and segment). Separate acquisition attach (module bought in the initial sale) from expansion attach (bought later). Eligible customers without the module and with related usage become the upsell list.

07
Deduplicating identical charge item rows.
Charge items are validated by the total

When a charge's extra amount is broken down by item, there may be no unique key and there may be legitimate identical rows, such as two items of the same value. Deduplicating throws away revenue. Validate by summing items against the charge total and create a non-itemized line for the difference, shown as a gap and never added to cross-sell. Refunds and deleted items stay out.

08
A single 90-day rule for every company.
Repurchase timing from each company's cycle

For recurring sales outside a subscription (packages, credits, one-off renewals), group the company's wins by day, compute the average interval between purchases over the last 6 to 12 months and flag repurchase timing when days since the last purchase exceed the average cycle minus a slack (for example, 7 to 14 days), with a declared floor such as 30 days. A company with a single purchase uses a declared default cycle.

09
Sending the whole base to the upsell queue.
Keep out of re-engagement who shouldn't get it

Exclude from the expansion queue accounts that are inactive, in cancellation notice or delinquent, those served by their own channel (distributors, large accounts with a dedicated team) and those flagged with a restriction. The exclusion list is written and reviewed by the manager.

10
Rewriting the queue every day without keeping history.
Measure whether the queue works

Store each entry into the repurchase or upsell queue with the date and the outcome: won, open, lost or no deal. The curve of wins by days after entry shows whether the timing is well calibrated and how long the team takes to act.

How each product movement is classified

By customer x product x month, comparing month end with the previous month end.

product already existed, its MRR went upUpsellend - start
new product, customer already payingCross-sellproduct MRR at end
same customer, plan or cycle changeMigration, outside natural expansion
canceled and re-signed within 30 daysMigration, not churn plus new
renewal with the same quantity and priceNo movement
product MRR went down, customer still payingProduct contractionstart - end
product went to zero, customer keeps another productProduct churnstart

Definitions

Expansion MRR
sum of end - start over customer x product pairs where MRR went up, with the customer paying in both months, excluding migration
Cross-sell
month-end MRR of products the customer didn't have the previous month, while paying the previous month
Migration
MRR change from a cycle switch, renewal or re-sign by the same customer; its own column, outside natural expansion
Attach rate
active customers with the module / active customers eligible for the module, at month end
New revenue from the base
(expansion + cross-sell) / (expansion + cross-sell + new-logo MRR), per month
Average repurchase cycle
average days between consecutive purchase days of the company in the window; default cycle when there is a single purchase
Repurchase timing
days since the last purchase greater than or equal to the larger of the floor and the average cycle minus the slack
Post-timing conversion
companies that entered repurchase timing and won a deal within N days / companies that entered

Pitfalls that already happened

Expansion vanished in the snapshot

The MRR table kept only the subscription's current state, and quantity increases on the same subscription never showed up as expansion.

Record item change events or a daily snapshot.

A renewal zeroed out month end

A filter that removed migration records zeroed the last day's MRR when the only record that day was a billing renewal, and the monthly view lost revenue every month.

Sum the month snapshot without filtering migration; separate natural and migration only in the movements.

Deduplication threw away revenue

Identical charge items were treated as duplicates. Compared with charge totals, reconciliation got worse: they were legitimate items of the same value.

Validate by the sum against the total and expose the difference as non-itemized.

False alarm from an external channel

The expansion-without-a-charge alarm flagged almost half the customers from an external checkout channel, which never creates an invoice in billing, against a few percent of the rest.

Restrict the check to monthly plans in channels that create invoices.

Holding counted in every brand

A contract closed at the holding showed up again in each subsidiary brand, and expansion by brand counted the same MRR more than once.

Allocate the holding's MRR across brands by a written rule and skip subsidiaries with their own contract.

Weekly buyers flooded the queue

With the cycle computed per deal, companies that closed several orders on the same day and bought every week entered repurchase timing almost every day.

Group purchases by day and apply a floor to the cycle.

Acceptance test

The case is done when every item passes.

Agent package

Paste into Claude, ChatGPT or any client with the Nekt MCP connected.

Full Markdown
Expansion and upsell
- Customer x product movement = product MRR at month end compared with the previous month end.
- Upsell = increase in a product the customer already had. Cross-sell = new product for a customer already paying.
- Migration (cycle switch, renewal, re-sign by the same customer) is its own column. Don't count it as expansion.
- A renewal with the same quantity and price is not a movement.
- An upsell won in the CRM is expansion, never new logo.
- Attach = active customers with the module / active customers eligible for the module.
- Charge items are not deduplicated. The difference to the charge total shows as non-itemized and doesn't go into cross-sell.
- Repurchase timing = days since last purchase >= max(<floor> days, average cycle - <slack> days), with purchases grouped by day.
- Out of the queue: inactive accounts, in cancellation notice, delinquent, own channel and restricted accounts.
Per-client exceptions:
- <client>: module <module> is only eligible on plans <plans>.
- <client>: segments <segments> don't go into re-engagement.

Variations

Expansion forecast per account

A calibrated model gives each account's upsell probability and expected MRR gain, and the top becomes the month's expansion queue.

Move to annual

A dedicated queue of monthly customers with stable usage to offer the annual plan, measured separately from expansion.

Holding and brands

Contract closed at the holding with usage by brand: allocate MRR by a written rule and don't count the same revenue in two brands.