Revvly
Docs
Guide

Handle a mid-cycle change.

Migration, plan change, or expansion — how to tell them apart, preview the proration, and pick between applying now and waiting for the renewal boundary.

01Name the change first

Three different operations look similar from the customer's side. A migration moves an existing pin to a newer published version of the same module/bundle/component. A plan change swaps the composition itself — a different bundle, a different module set or tier. An expansion records an addition on top of the current plan — a raised commitment, an added module. Picking the right one keeps the version history and the MRR movement classification honest.

Which operation fits the change
  1. Customer changes
    Something about the current plan is different.
  2. Migration
    Moves an existing pin to a newer published version.
    or
    Plan change
    Swaps the composition: another bundle, module set or tier.
    or
    Expansion
    Adds on top of the plan, such as a raised commitment or module.
Pick by what changes: the version, the composition, or something added on top.

02Preview the money

calculatePriceChange previews the pricing impact of a proposed change; calculateProratedAmount previews just the prorated charge or credit for the remainder of the cycle. Both are read-only. Every dashboard flow shows this preview before the confirm button for a reason.

03Choose the timing

Migrations and plan changes take an explicit timing: MID_CYCLE_PRORATED applies now and issues an adjustment invoice for the remainder of the period; NEXT_RENEWAL queues a pendingMigration that the renewal boundary applies cleanly, with no mid-cycle invoice. Queued changes can be cleared with cancelPendingMigration any time before they apply.

Timing of a migration or plan change
  1. Migration or plan change
    Takes an explicit timing.
  2. MID_CYCLE_PRORATED
    Applies now. Adjustment invoice for the rest of the period.
    or
    NEXT_RENEWAL
    Queued as pendingMigration. Applied at renewal, no mid-cycle invoice.
Apply now with an adjustment invoice, or queue it for the renewal boundary.
Where
  1. Subscriptions
  2. open a subscription
  3. the actions menu
  4. Change plan or version

The same modal previews the money and takes the timing, so the figure and the decision are on one screen.

04How proration is calculated

The proration model comes from the Variable Component (or the subscription's base terms): FULL_MONTH charges the month of the change in full plus every month left in the period (a seat added in month 3 of a yearly term bills 10 of 12 months), DAILY charges by days remaining, NONE skips proration entirely. A mid-cycle upgrade from $49 to $79 with 14 of 30 days left under DAILY prorates to (79 − 49) × 14⁄30 ≈ $14.

05A change inside a prepaid span asks about the cash

If the customer has already paid for periods ahead, proration alone would charge the price difference for the current period only — every remaining prepaid period bills nothing, so the rest of the span would silently keep the old price. Revvly refuses to guess and asks: "Charge the difference now" raises one catch-up invoice covering the rest of the current period plus every whole period the prepayment still covers, and "Do not charge until the span runs out" applies the change and bills nothing more. Downward, "charge now" is a credit note, symmetrically — the money for those periods is already in. The plan changes immediately either way and MRR moves with it; this decides cash only. The catch-up is a one-off proration line, never a rate, so nothing restates MRR at a figure no renewal will charge.

Where
  1. Subscriptions
  2. open a subscription
  3. Change plan or version
  4. Inside a prepaid span

The choice appears only when the subscription is inside a live prepaid span, and the modal will not submit without it.

06Expansions land in the record

createSubscriptionExpansion writes the expansion with its prorated amount and effective date, and emits an EXPANDED (or CONTRACTED) lifecycle event with the signed MRR delta. That delta is what Expansion MRR and NRR are built from — expansions are not just invoices, they are analytics inputs.

07Everything is in the version history

Every pin move, plan change, component attach/detach, and grandfathering decision appends to the subscription's versionHistory — queryable via subscriptionVersionHistory, oldest first. When someone asks "what changed on this account and when," that log is the answer.