<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>ShipRev Blog</title>
    <link>https://shiprev.dev/blog</link>
    <description>Notes on the design behind ShipRev: identity, subscriptions, metering and entitlements on one customer record.</description>
    <language>en</language>
    <atom:link href="https://shiprev.dev/blog/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>When a Customer Runs Out of Quota: Block, Bill, Prompt or Cut Off</title>
      <link>https://shiprev.dev/blog/quota-exhausted-choices</link>
      <guid isPermaLink="true">https://shiprev.dev/blog/quota-exhausted-choices</guid>
      <pubDate>Tue, 13 Oct 2026 00:00:00 GMT</pubDate>
      <dc:creator>ShipRev</dc:creator>
      <category>Pricing in Practice</category>
      <description>What a usage-priced product can do when a customer uses up their allowance, who pays for each choice, and why every option leaves a gap between crossing the line and stopping.</description>
      <content:encoded><![CDATA[<p>If you sell plans with a monthly allowance, sooner or later a customer uses all of it before the month is over. What your product does at that moment is a pricing decision, even if nobody made it on purpose. Often it was made by whichever piece of code happens to check the counter first.</p>
<p>There are four common answers. None of them is free: each one moves a cost onto someone. This post walks through who pays in each case, what you need to know to choose, and one constraint that applies to all four.</p>
<h2>A worked example</h2>
<p>Take a document-processing API. Its middle plan includes 10,000 pages a month, and every page costs you something, because you pay a third-party service for each call. On the 20th of the month, one customer's integration sends its 10,000th page.</p>
<p>At that point your product can:</p>
<ol>
<li><strong>Block</strong>: reject further requests until the next period or until the customer upgrades.</li>
<li><strong>Allow and bill</strong>: keep serving, and charge for the pages above the allowance as overage.</li>
<li><strong>Allow and prompt</strong>: keep serving for now, tell the customer they are over, and ask them to upgrade.</li>
<li><strong>Cut off at a ceiling</strong>: keep serving past the allowance, but stop at a spending ceiling that you or the customer set in advance.</li>
</ol>
<p>One billing guide calls the first a hard cap, where usage stops at the line, and the second a soft cap, where usage continues and the customer pays for crossing the line through overage charges, slower service or fewer features. The third and fourth are soft caps with different rules for when to stop.</p>
<h2>Block: reliable, and it lands on your heaviest users</h2>
<p>Of the four, a hard cap comes closest to stopping your cost at a known point; the usage that gets through before the block takes effect is covered below. It is also the option that hurts the customer who uses you the most, and that customer may be using you heavily because their own business is growing on top of yours.</p>
<p>The cost of blocking is easier to see when an infrastructure provider offers it to its own customers. One hosting platform lets a team set a spend amount, and its documentation says plainly that the amount does not stop usage on its own. To actually stop, you turn on an option that pauses production deployments. When that happens, the sites, APIs and functions in those projects stop serving visitors and return an error, and each project has to be resumed by hand. Raising the spend amount afterwards does not bring them back.</p>
<p>That is what a hard cap looks like from the receiving end: everything behind the limit goes down at once, including whatever your customer's own users were in the middle of. If you block at the plan allowance, work out what a blocked request looks like to your customer's end users, and whether the customer had any warning before it happened.</p>
<h2>Allow and bill: the risk moves to collection</h2>
<p>If you keep serving and bill for the overage, nobody is locked out. The cost moves to you instead. You have delivered the usage and paid your own suppliers for it, and the money arrives only when the invoice is paid.</p>
<p>Some payment providers offer tools for this. One provider's billing thresholds issue an invoice early, as soon as a customer's accumulated usage in the period reaches an amount you set, to limit how much a customer can owe between invoices. Thresholds do not stop usage, and a threshold invoice only includes the usage the provider had received when it was created.</p>
<p>An early invoice shortens the time you are exposed, but the customer still has to be able and willing to pay it. If a large overage came from a runaway script rather than real demand, you may be asked to forgive usage that you have already paid your suppliers for.</p>
<h2>Allow and prompt: only as good as the timing</h2>
<p>The third option keeps the customer working and turns the moment into an upgrade conversation. Whether that works depends on when the customer sees the prompt.</p>
<p>A prompt is an event your system has to produce and deliver. The same payment provider can send you a webhook when a customer's usage crosses a value you set, including a kind of alert that fires only once per customer. The alert tells you; it does not block anything, and what happens next is code you write. The billing guide mentioned above suggests warning at several points, such as 50%, 80% and 100% of the allowance, so that the last warning is not the first.</p>
<p>If the first message a customer sees is "you are over your limit", the prompt has already turned into a surprise on the invoice.</p>
<h2>Cut off at a ceiling: depends on how recent the numbers are</h2>
<p>The fourth option combines the others: let usage run past the allowance, bill for it, and stop at a ceiling. Some infrastructure tools let you connect an alert to an automatic action. One major cloud provider's budget notifications can trigger your own code, and its documentation gives disabling billing for a project as an example. Another major cloud provider lets a budget threshold run actions, either automatically or after someone approves them, such as attaching a policy that prevents new resources from being created, or acting on specific compute or database instances.</p>
<p>A cutoff can only act on the usage it can read, and the documentation of each of these providers describes a delay before usage shows up in its numbers.</p>
<h2>Every option leaves a gap</h2>
<p>Read together, the documentation of the services above makes two points.</p>
<p><strong>An alert is not a limit.</strong> One major cloud provider states that a budget that only sends alerts does not cap usage or spending. The hosting platform says the same about its spend amount. The payment provider's usage alerts notify you, and its thresholds invoice early. Stopping is a separate decision, and someone has to make it.</p>
<p><strong>Usage data arrives late.</strong> The first cloud provider notes a delay between when a resource is used and when its cost shows up in billing. The second updates budget information up to three times a day, usually 8 to 12 hours apart, so spending can already be past a threshold when the notification arrives and can keep changing after it. The hosting platform checks spend every few minutes, so a pause can come several minutes after the line is crossed, and it suggests setting the amount below what you can actually afford. The payment provider processes usage events asynchronously, so usage totals and upcoming invoices may not yet include events it has just received.</p>
<p>So whichever option you choose, some usage will happen between crossing the line and anything happening in response. The design question is who absorbs that usage:</p>
<ul>
<li>If you block, decide how far past the allowance you accept before the block takes effect, and whether you bill or forgive that part.</li>
<li>If you cut off at a ceiling, set the ceiling below the number you truly cannot exceed, leaving room for the usage that can build up during the delay.</li>
<li>If you prompt or bill, check that the warnings come early enough for the customer to act before the gap matters.</li>
</ul>
<h2>How to choose</h2>
<p>Three questions settle most of the decision.</p>
<ol>
<li><strong>Who pays for each unit of usage?</strong> If every unit costs you money at a supplier, such as an inference call, a third-party API or compute time, open-ended overage puts your margin at risk, and a ceiling matters more. If the cost of one more unit is close to zero, blocking mostly costs you goodwill.</li>
<li><strong>Can the customer see their usage before the limit?</strong> If customers can check their usage and get warnings ahead of time, a block or an overage charge is something they saw coming. If they cannot, any of the four will feel like a surprise.</li>
<li><strong>Can you collect the overage?</strong> Billing for overage assumes the customer will pay the larger invoice. For customers on monthly card payments with no contract, that assumption is weaker than for customers with a signed agreement.</li>
</ol>
<p>When a customer is upset about a large bill, the conversation often turns to price. Usage the customer can see, warnings before the limit and a ceiling they agreed to all speak to the surprise itself, which a lower rate does not. These are worth deciding before you tune the numbers on the pricing page.</p>
<h2>When you are the one being metered</h2>
<p>The same choices apply in reverse when your product depends on a service that charges per call. One payment provider's tax calculation API, for example, includes a set number of calculation calls with each transaction and charges for each call above that. An integration that calls it more often than it needs to, on every change to a cart or inside a retry loop, can make far more calls than you planned for, and the bill follows the calls rather than your revenue.</p>
<p>Before you add a per-call dependency:</p>
<ul>
<li>Read the supplier's pricing for what is included and what is charged per call.</li>
<li>Put your own counter and limit in front of the calls, so a bug stops at your limit rather than at the end of the billing period.</li>
<li>Turn on the supplier's alerts where they exist, and treat them as a notice that may arrive late, not as a stop.</li>
</ul>
<p>This post was written by the team building ShipRev, which has not been released. It describes common approaches to usage limits, not a feature of ShipRev.</p>]]></content:encoded>
    </item>
    <item>
      <title>Changing a Plan's Price When Customers Are Already on It</title>
      <link>https://shiprev.dev/blog/repricing-existing-customers</link>
      <guid isPermaLink="true">https://shiprev.dev/blog/repricing-existing-customers</guid>
      <pubDate>Tue, 13 Oct 2026 00:00:00 GMT</pubDate>
      <dc:creator>ShipRev</dc:creator>
      <category>Pricing in Practice</category>
      <description>What happens to existing subscribers when you change a plan's price or limits, the common ways to handle them, and the state that is easy to miss when you move them.</description>
      <content:encoded><![CDATA[<p>You have been selling two or three paid plans for a year or two. Now one of them needs to change: the price goes up, a limit moves, or one plan becomes two. The new customers are easy. The hard part is everyone who already pays for the old version.</p>
<p>Their terms are rarely in one place. The price lives in the payment provider's subscription. The plan name sits in a column in your own database. The limits are checked somewhere in your code. A handful of customers have a discount or a special arrangement that someone agreed to over email. Changing the plan means deciding what happens to all of that for every existing subscriber.</p>
<p>This post walks through what the payment side does and does not do for you, the common ways teams handle existing customers, and the state that tends to get lost when they are moved.</p>
<h2>What the payment side does when a price changes</h2>
<p>Using Stripe as the example, since its behavior is documented in detail, a few facts from its documentation shape every option below.</p>
<p><strong>A price cannot be edited.</strong> Once a price object exists, its amount is fixed; only fields such as its metadata, nickname and active flag can change. Changing what a customer pays means creating a new price and moving the subscription to it (<a href="https://docs.stripe.com/products-prices/manage-prices">Manage products and prices</a>).</p>
<p><strong>Retiring a price does not move anyone.</strong> Archiving a price stops new purchases of it. Existing subscriptions on that price stay active until they are cancelled. Taking an old plan off sale leaves every current subscriber exactly where they were.</p>
<p><strong>Moving a subscription is an explicit step, with two details to get right.</strong> To switch a subscription to a new price you name the subscription item being replaced; otherwise the new price is added alongside the old one and both are billed. The quantity also resets to one unless you pass it again (<a href="https://docs.stripe.com/billing/subscriptions/change-price">Change the price of existing subscriptions</a>).</p>
<p><strong>Proration covers money paid in advance, not usage.</strong> A mid-cycle change is prorated by default: the rest of the period is charged at the new price. You can preview this or turn it off, and a negative proration is not refunded automatically. Stripe's documentation states that usage-based billing is not subject to proration (<a href="https://docs.stripe.com/billing/subscriptions/prorations">Prorations</a>). If you want the switch to happen at the end of the period instead, the documentation points to subscription schedules.</p>
<p>That last point matters most for this post. The payment side settles the money for the part of the period already paid for. What happens to the customer's usage counts, remaining allowance and limits when the plan changes is not decided there. Wherever those numbers live, deciding what happens to them is your call.</p>
<h2>Ways to handle existing customers</h2>
<p>None of these is the right answer in general. Each has people who argue for it in public, and each has a cost.</p>
<h3>Keep them on the old plan</h3>
<p>The old plan stops being sold, and everyone already on it keeps their price and limits for as long as they stay. One software company wrote publicly, when it retired a product, that it would take no new users but would look after the existing ones forever.</p>
<p>This is the simplest thing to tell customers, and the payment side already behaves this way when you archive a price. The cost builds up on your side. Each plan you keep is another set of limits your code has to recognize, another row in every report, and another case to test when you change anything nearby. Customers on the same features end up paying different amounts. One founder has written that, two years after keeping existing customers on their old pricing, a noticeable part of their revenue came from plans they no longer sold, and that the extra plans added operational complexity.</p>
<h3>Move them at their next renewal, with a window to lock in</h3>
<p>The new price applies from each customer's next renewal after a set date. Some teams also offer a window before that date: renew early, or switch to annual billing, and keep the old price for one more term. A team chat product took this approach for its first price increase in 2022, according to reporting at the time.</p>
<p>This spreads the change across a full billing cycle, and nobody is moved in the middle of a period they have already paid for. It also means that for months you are running both the old and the new terms at once, and each customer's switch date depends on when they last renewed.</p>
<h3>Move them to the new price with an explicit discount</h3>
<p>Instead of keeping the old plan, you move everyone to the new one and give existing customers a discount on it, stated as a loyalty discount. One pricing-analytics founder has argued for this in a talk, as later summarized by an investor: since price increases are inevitable, avoid leaving customers on legacy pricing, and give existing customers a loyalty discount on the current plan instead.</p>
<p>You end up with one plan to maintain and one set of limits. The discount, though, becomes a long-lived piece of state of its own, which leads to the next section.</p>
<h3>Move them now</h3>
<p>The change applies to everyone at once. Mid-cycle, the payment side prorates the money by default. Everything that is not money (usage so far this period, what is left of an allowance, any customer-specific limits) has to be carried across by you.</p>
<p>This gets everyone onto the same terms fastest. It also puts the most state in motion at a single moment, and the customer notices the change in the middle of a period.</p>
<h3>Variations</h3>
<p>Teams often mix these. Light users might be moved at once while heavy users get a longer window, or a plan's price might be held while its limits change. Each variation adds a rule that has to be applied correctly to every subscriber, so it helps to write the rules down before deciding which customers fall under which.</p>
<h2>Old prices you cannot see</h2>
<p>Not every old price shows up as an old plan. Discounts are a common place for one to hide.</p>
<p>In Stripe, a coupon can apply once, for a number of months, or forever. If a coupon is set to apply forever and also has an expiry date, the expiry date only stops new customers from redeeming it; anyone who already has it keeps the discount forever. Deleting a coupon stops it from being applied to new subscriptions and invoices, but it does not remove it from subscriptions and invoices that already have it (<a href="https://docs.stripe.com/billing/subscriptions/coupons">Coupons and promotion codes</a>).</p>
<p>So a launch promotion that "ended" years ago can still be lowering what some customers pay today, under a plan whose list price you have since raised. Changing the subscription's discount does not trigger proration either; the new discount applies from the next invoice. Before a price change, it is worth listing every discount still attached to an active subscription, not only the ones you can still issue.</p>
<h2>The state that gets lost when you move customers</h2>
<p>When a customer moves from one plan to another, four kinds of state need a decision, and they are easy to miss because none of them is the price.</p>
<ol>
<li><strong>Consumed counts.</strong> How much the customer has already used this period. Does it carry over against the new limit, or reset?</li>
<li><strong>Unused balances.</strong> Prepaid amounts or credits the customer has not spent yet. Do they move across at the same value, convert, or expire?</li>
<li><strong>Remaining allowance.</strong> What is left of a quota under the old plan. If the new plan's limit is lower than what the customer has already used, what happens on the first request after the switch?</li>
<li><strong>Per-customer overrides.</strong> The higher limit someone was given as a favor, the feature turned on for one account, the arrangement made during a sales call. These are usually the least documented and the most likely to be overwritten by the new plan's defaults.</li>
</ol>
<p>For each of the four, it is worth deciding in advance what happens to a customer who is moved now, at renewal, or not at all, and checking that every place that stores the number agrees with the decision.</p>
<h2>Estimating the impact before you change anything</h2>
<p>Before choosing an approach you usually want to know how many customers each option affects and by how much. If that estimate comes from exporting subscriptions into a spreadsheet, keep in mind what the export does not contain. It is a snapshot of the payment side at one moment. It will not show usage, remaining allowances or overrides kept elsewhere, and it is out of date as soon as anyone subscribes, upgrades or cancels. The estimate is only as complete as the sources joined into it.</p>
<p>Telling customers is part of the plan too. Your own terms, and the law where your customers are, may require advance notice of a price change; check with whoever is responsible for your terms before you set dates.</p>
<h2>A checklist before you change a plan</h2>
<ul>
<li>Decide which approach applies to which customers: keep, move at renewal, move with a discount, or move now.</li>
<li>Create the new price; do not expect retiring the old one to move anybody.</li>
<li>When switching subscriptions, name the item being replaced and pass the quantity.</li>
<li>Decide whether a mid-cycle switch is prorated, and remember that proration covers prepaid money, not usage.</li>
<li>For each of consumed counts, unused balances, remaining allowance and overrides, write down what happens on the switch.</li>
<li>List every discount still attached to an active subscription, including ones that can no longer be redeemed.</li>
<li>Check that the plan recorded in your database, the limits in your code and the subscription in the payment provider all agree for a sample of customers after the change.</li>
</ul>
<p>ShipRev is being built to keep a SaaS product's identity, subscriptions, metering and entitlements on one customer record. It has not been released, and this post describes a situation teams face, not something ShipRev does today.</p>]]></content:encoded>
    </item>
    <item>
      <title>Designing Identity, Subscriptions, Metering and Entitlements Around One Database Transaction</title>
      <link>https://shiprev.dev/blog/four-domains-single-transaction</link>
      <guid isPermaLink="true">https://shiprev.dev/blog/four-domains-single-transaction</guid>
      <pubDate>Sat, 10 Oct 2026 00:00:00 GMT</pubDate>
      <dc:creator>ShipRev</dc:creator>
      <category>Core Invariants</category>
      <description>Why ShipRev is designed to keep the four pieces of commercial state for a SaaS product in one process and one PostgreSQL database, written to in one transaction.</description>
      <content:encoded><![CDATA[<p>A SaaS team that sells several plans with quotas usually keeps the state behind them in several places: a sign-in service, a payment provider, a usage counter and its own code.</p>
<p>ShipRev is designed to hold that state on one customer record, in one process and one database, so that a change to one of the four is written in the same transaction as the others. Here is how the four are meant to fit together:</p>
<ol>
<li><strong>Catalog and tiers</strong>: products, capabilities and the tiers that bundle them, published as versions.</li>
<li><strong>Subscriptions</strong>: subscription state, invoices and prepaid balances, connected to your own Stripe account.</li>
<li><strong>Metering</strong>: usage events recorded against each customer, with reservations that are confirmed or released.</li>
<li><strong>Identity</strong>: end users, the organizations they belong to, and the boundary between one customer's data and another's.</li>
</ol>
<p>Changes to configuration, subscriptions and entitlements are designed to be recorded in an append-only change log, so that each change can be traced afterwards.</p>
<p>ShipRev has not been released. This post describes its design, not a product you can use today.</p>]]></content:encoded>
    </item>
  </channel>
</rss>
