Owostack
Guides

Switch plans

Implement upgrades, downgrades, and lateral moves

How to switch plans

This guide shows how to move a customer between plans using attach(). Plans must be in the same plan group for Owostack to treat the change as a switch rather than a new subscription.

Upgrade a customer

Call attach() with the new plan. Owostack detects that the customer already has a subscription in the same plan group and initiates an upgrade.

const result = await owo.attach({
  customer: "user_123",
  product: "pro-monthly", // higher-priced plan in the same group
});

if (result.checkoutUrl) {
  // Customer needs to pay the difference
  console.log(result.checkoutUrl);
} else {
  // Upgrade applied immediately (e.g. free → paid handled inline)
  console.log("Upgraded:", result.subscription);
}

Upgrades take effect immediately. Entitlements are re-provisioned so the customer sees the new plan's features right away.

Downgrade a customer

Same call, lower-priced plan:

const result = await owo.attach({
  customer: "user_123",
  product: "starter", // lower-priced plan in the same group
});

Downgrades are scheduled for the end of the current billing period. The customer keeps their current plan's features until then. After the period ends, Owostack switches the plan and re-provisions entitlements.

Lateral moves

If the new plan has the same price as the current one, the switch is applied immediately with no checkout required.

const result = await owo.attach({
  customer: "user_123",
  product: "pro-annual", // same price tier, different interval
});

// result.subscription.status === "active" — no checkout needed

Plan group requirement

Plans must share a plan group for switching to work. If you call attach() with a plan in a different group, Owostack creates a second subscription instead of switching.

Set the plan group when creating plans in the dashboard or via plan() in code:

plan("starter", {
  name: "Starter",
  price: 0,
  currency: "USD",
  interval: "monthly",
  planGroup: "main",
  features: [apiCalls.limit(100)],
});

plan("pro", {
  name: "Pro",
  price: 2000,
  currency: "USD",
  interval: "monthly",
  planGroup: "main", 
  features: [apiCalls.limit(10000)],
});

What changes during a switch

  • Subscription state may be updated at the provider
  • Entitlements are re-provisioned so the customer’s features match the new plan
  • Scheduled downgrades are stored until the period ends
  • Use a preview endpoint (or dry-run) to show:
    • whether it’s immediate vs scheduled
    • whether payment is required
    • what proration will be charged

If you’re using the dashboard/API, expose this preview in your billing settings page.

On this page