- Published on
Building Recurring Orders With Stripe Subscriptions
Intro
You want to build a recurring order platform, and you're already using Stripe as a Payment Api Gateway. Ideally, you'd rather not bring in more tech right away, and Stripe's UI gives you some built in tools for your internal teams to troubleshoot customer payment issues, update subscribed products, and update payment information.
Stripe Subscriptions is part of their Billing platform - an additional add-on which comes with a ton of useful features. Keep in mind the more you use Stripe's platform the more of a cut they'll take, but that's often saving you money in the long run. Especially for early stage companies, the sooner you have a plausible digital product and effective internal tooling, the sooner you can get out of the day to day and switch focus to solving bigger business problems.
Getting Started
Create Your Product Catalog
Use their Product Catalog feature to create your Stripe Products. Then, create additional Stripe Prices as needed. Importantly - Stripe Price also embeds Product Frequency - meaning that you'll need Stripe Prices for every recurrence frequency you intend to offer. Stripe does not allow mixing frequencies on the same Subscription for good reason - all products need to align to recur at the same time in order to create an invoice.
Create Subscriptions
Using the Stripe API (or UI to get started - their UI issues public API facing statements so you can actually observe the API interactions the UI makes to understand how to replicate UI features!) create your first Subscriptions. By default, creating a Subscription will also create the first Invoice (using the default payment method), then create a subsequent pending Invoice at the next natural recurrence anchor.
React to Successful Payments
Once Stripe charges the customer, you'll receive a webhook and can do what you need to do to fulfill the order. Off you go! :boom:
Tips and Tricks
Moving the Next Recurrence
This is a huge gotcha. Stripe tries to model Subscriptions first as the "access to a resource" or "metered billing" use case, and makes the "ship products on a cadence" use case actually fairly difficult. In order to move the next billing date around without impacting the price of the Invoice, you have to set the Subscription into "trial" first. This way, Stripe will turn off any sophisticated proration smarts you don't want. There are unfortunate implications to using this hack. You will not be able to trust the built in Stripe Subscription reporting - because it doesn't forecast projected revenue correctly from "trial" subscriptions. Further, you cannot actually offer a trial cleanly, because you're using this trial feature as a hack to work around recurring billing.
Starting a Subscription in the Future
You don't necessarily have to invoice immediately. Use the billing_cycle_anchor
field to specify a time in the future.
Aligning the Product Quantity to Build a Shipping Buffer
We try our best to ship products to customers on a very predictable schedule. It is best to be a little early than to be late. In order to achieve this, we create the Subscription then shorten the first recurrence period by default to account for any delays in shipping and build in a small fixed buffer for every subsequent send. We use the "trial hack" above to achieve this.
Proration
You never want proration. Always use proration_behavior: 'none'
Payment Method
payment_behavior: 'allow_incomplete'
creates the Subscription even in the case of a failed initial Invoice. You probably want this if you're creating Subscriptions on behalf of customers outside of a synchronous customer flow.
Useful Webhooks
Stripe gives you a configurable "Upcoming Invoice" webhook. You can specify how many days in advance you'd like. Hand this to your CRM to make sure customers are reminded that they've got an upcoming shipment - this is a good chance to ensure customers aren't surprised and try to refund their unwanted order, as well as remind them to ensure the right credit card is on file, address is accurate, etc. Stripe also creates an Invoice an hour before charging it. You can use this silent period to do any triple checking you need to do on your side (look at inventory for example) to ensure you don't need to issue a chargeback. They're expensive, suck up customer success agent time, and are a subpar user experience!
Test Clock
It is difficult to test time related tasks in a sandbox environment without a time machine. The Test Clock gives you a time machine (how cool!). You can create Stripe Subscriptions into a Test Clock, then move the Test Clock forward to move forward in time and emulate sending webhooks and charging the customer. To be successful with a Test Clock implementation, implement a timeService
in your app that uses now()
OR the Test Clock time if your app or customer is running against a Test Clock.
Failed Invoices Vs Updating Card Details Vs Smart Retries
This one is a toughie. Consider this flow -
- Customer invoice attempts to charge but the card fails
- Customer is alerted to failure with a call to action to update the card
- Failing invoice is set into Smart Retries, meaning it will periodically re-attempt to charge the card
- Customer updates their card information then charges the card using a customer portal
- Smart Retry successfully charges the old invoice, resulting in a double charge There are a few ways to prevent this, but it requires thinking through your use cases. One example would be to use the invoice create quiet period mentioned earlier to check for recent charges for that product and sidestep! For our scenario, there are practically zero reasons a customer would actually want quick double charges for a single product.
Alternatives
Stripe Subscriptions isn't the only game in town. You may want to take some time to evaluate alternatives to see whether they fit your use case better.
Home Grown Recurrence Engine
Building a recurrence engine from scratch is one option. It isn't terribly complex, but you'll want some folks with system architecture chops to design and implement it.
The correct data model will depend on your exact needs. I've built or designed a recurrence engine twice and they share a few overlapping traits. First, you'll need to model the element that is due to recur on a cadence (for ecommerce - the customer's subscribed products). Next, you'll want a one-to-many to keep track of the instances of the recurrence.
Here are a few design tradeoffs to think about early on -
- When a new subscription is created, do you create "pending" recurrences, and if so, do you create all of them, or just the next that is due to recur? Seeding a single "pending" recurrence is the easiest and a good tradeoff between flexibility and complexity. This is what Stripe chooses as well.
- If an instance of a recurrence can not charge (or otherwise passes without being able to fire) - what happens next? Stripe actually gives you a choice. By default, it allows the invoice to lapse into a past due state (this is where smart retries can kick off). A new pending recurrence is then created at the next natural recurrence based on the frequency of the subscription recurrence items. The subscription can continue to operate, or pause, at this point.
- Put your thinking hat on to ensure proper tracking and reporting out of the gate. Can subscriptions change? How about individual instances of a recurrence? Ensure you've got a data model built in to effectively track this. What we like to do is attach
_history
tables to slowly mutating data structures. Then, we add a trigger to write a new row to the history table every time columns get updated with an optional (but strongly recommended)details
column explaining the rationale that caused the change. This table can then be fed by webhook events, customer portal changes, and internal admin changes, consolidating the timeline of changes into a single timestream that you can use as an effective audit trail when troubleshooting (and to present using that cooltimeline
widget you can never find a use case for!)
Reasons you'd build your own
- You need the flexibility
- You have use cases that don't map easily into Stripe Subscriptions - you'll need to wire up hacky workarounds constantly to make it work
- You have massive trust in your dev team to build something sophisticated and get it right the first time
- You'd rather treat Stripe as a "dumb" payment api gateway to keep costs down and prevent vendor lock-in
Other Vendors
Before locking in an architecture choice this important, you may want to consider a vendor that provides recurrence that integrates with Stripe (or your preferred payment api gateway). Options include Recurly, Chargebee, and Recharge. Especially for ecommerce, you should take a look at Commercetools who recently (2025) launched a recurring orders feature.