Farther ShoreDocs
Go to Farther Shore
Design and operate commerce
Entitlements vs economics
Cohorts & releases
Plan transitions
Connect Stripe
Subscriptions & usage
Plan changes
Safe workflowWhat the diff answersWho a change reachesSubscriber-initiated plan changesActivation is per businessRecovery
Billing strategies
Pricing catalogs
Funding & allowances
Economic agreements
Commercial releases
Bill preview API
Usage & billing policy
Ledger & settlement
Subscription + overage
Freemium that converts
Add a trial
Add a spend cap
Change a price
Prepaid wallet
Meter AI tokens
commerce HTTP contracts
Status
Docs/Monetize/Plan changes

Plan changes

Reprice or reshape a plan by publishing a new commercial release; existing subscriptions keep their pins.

Change a plan by editing its fs.plan() declaration — or the pricing catalog it binds — and pushing the managed repository. Do not mutate live plan, price, or catalog rows through an API. Bespoke per-customer terms are economic agreements, not repo edits.

Safe workflow

bash
farthershore build
farthershore commercial-release diff <from-release.json> <to-release.json>
git push
farthershore apply-timeline inspect <business> <commit-sha> \
  --env production \
  --format json

Inspect the apply check and publish only after reviewing the current-head result. For an active repository-managed business, create a GitHub Release for that exact commit. farthershore business publish is only the first-activation command for a business that is still DRAFT.

What the diff answers

farthershore commercial-release diff compares two compiled release manifests and reports:

  • compiled plans added, removed, or changed — a compiled plan changes when its route grants, structural limits or recurring fee change, not when you edit a catalog rate;
  • rating-context versions added or removed — a catalog or modifier change mints a new rating context and leaves the compiled plan alone, so a price-only edit shows up here and only here;
  • every changed manifest path and any compatibility-fence change;
  • unchanged: true when both manifests hash identically — republishing identical content reuses the same release id.

Who a change reaches

ChangeNew subscriptionsExisting subscriptions
Recurring price up or downnew pricekeep their recurring-price pin
Catalog rate change under a pricing.current() plannew ratenew rate from the activation of the release, forward only — never rerated retroactively
Catalog rate change under a fixed-version agreementn/auntouched; the agreement is require_amendment by definition
New meter or measurerated per catalogagreements apply their NewMeterPolicy / NewMeasurePolicy; plain subscriptions rate it
Funding bucket amount or onExhaustionnew policynext issuance follows the new plan version they are moved to; current buckets are unchanged
Route grants and structural limitsappliesapplies with the release they are served under

The generalized "move every subscriber to the latest plan" operation is deferred to post-launch: it is strictly a pricing rebind (repoint the recurring pin, refresh non-current bindings, open a new rating segment), and it is not part of prepare, publish, or activation.

Subscriber-initiated plan changes

Everything above is a BUILDER change — a new release of the catalog. A subscriber changes their own plan from the portal, and that path has its own timing rule:

MoveEndpointWhen it takes effect
Free floor → a chargeable planPOST /me/subscription/checkout-sessionimmediately, once checkout completes
Cheaper plan → dearer plan (upgrade)POST /me/change-planimmediately
Dearer plan → cheaper plan (downgrade)POST /me/change-planat the end of the current period
Any paid plan → back to the free floorPOST /me/change-planat the end of the current period

The rule is a single comparison of the recurring fee: a strictly dearer target is applied immediately, and everything else is scheduled for the period boundary. A downgrading subscriber therefore keeps the plan they paid for until it expires — there is no mid-period repricing and no refund to compute.

This means cancelling is not the only way down. The portal's plan list offers every plan except the one the subscriber is already on, including the free floor, so "I want to spend less" does not have to become "I want to leave". Cancelling ends the subscription; downgrading to the free floor keeps the account, its keys, and its history.

Moving a live subscription onto the free floor can only be scheduled, never forced through immediately: asking for an immediate move is refused with 409 PAID_TO_PROVIDERLESS_REQUIRES_PERIOD_END.

Activation is per business

Publication writes an immutable release; activation appends an entry to the business's release log and promotes a per-business pointer. Business A's publish or rollback never touches business B. Requests already admitted under the previous release complete under it. See Commercial releases.

Recovery

Publishing is idempotent. Inspect workflow and Apply Timeline state before issuing another mutation.

A rollback appends a new release-log entry that points at an older immutable release; it never rewrites a release, never re-rates usage that was admitted under the rolled-back release, and does not erase invoices or ledger history.

PreviousSubscriptions & usageNextBilling strategies

On this page

Safe workflowWhat the diff answersWho a change reachesSubscriber-initiated plan changesActivation is per businessRecovery