Building a Billing System

Photo by on Unsplash

Building a Billing System


6 min read


Building a billing system is complex and Stripe helps a lot. But using Stripe can lead to tax complexity when selling worldwide and Paddle could be the solution. But using Stripe vs. Paddle is not a simple choice and often the choice depends on available resources to quickly get to market.

I am a big fan of Stripe and in the past I have used Stripe for building billing systems for SaaS solutions. Though it sounds pretty simple that user enters their credit card details and we just have to charge them every month, things can get really complex when building a billing system.

Stripe's documentation is great, APIs are pretty simple and the ability to get everything to work in test mode before switching to real production mode is amazing. However, Stripe has tons of options and there is no one solution that just works for all kinds of billing processes. Things can get really complex if there is an existing enterprise downstream system that needs to be integrated to. For example, user pays with credit card but that revenue needs to be recognized via an enterprise process or system.

In this article I will be talking about my experiences with Stripe Billing (subscription as a service) and as a startup I do not yet to deal with complex revenue recognition systems. Whenever a customer signs up for my product, we leverage Stripe for managing all aspects of the subscription.


Customer is the core object representing the user paying for the service. This includes the email address, billing profile (addresses) about the customer. Beyond billing reasons, we don't have any use case for storing customer's address. So, this information is only persisted to Stripe and not stored in our systems.


Products are what we sell to the customer. Each product (represented by Price) in Stripe is a SKU that a customer can sign up for. We create a product in Stripe for all possible customer's plans including Free plans, Paid plans and any add-ons the customer can signup for.

Payment Method

Stripe supports varieties of payment methods, Credit cards, Google Pay, ACH, Wires etc. For our app to be in compliance with PCI standards, any payment information that customer enters must not touch any of our services and should be transmitted directly to Stripe from our application. Stripe provides JS library for this and it simply renders a hidden iframe without app.


As a seller, we are responsible for remitting taxes wherever we are registered. In many jurisdictions, there are minimum amounts or minimum number of transactions that we must incur before registering for tax ID. Stripe Taxes help with monitoring tax thresholds for all our transactions. So, whenever a customer switches to a paid subscription we collect customer's address for these reasons.

Signup flow

When a customer signs up, we create a customer record in Stripe and create a subscription in Stripe with our Free SKU. Every customer who signs up will start with the free product. Stripe also has support for setting up a trial.

Upgrade flow

When a customer uses the product and finds value, they would upgrade to one of our Paid plans. Paid plan will grant access to more features in the product, so any upgrades must be immediate so the customer immediately realizes the value. When a customer attempts to upgrade, we simply update the existing subscription. Remove the free SKU from the subscription and add the Paid SKU to the subscription, that just triggers a charge on the payment card.

Additional SKUs

A customer can signup for additional products during the subscription process. Stripe supports adding additional SKUs to existing subscription and depending on the business process, prorations can be triggered. Whenever a customer adds additional products to the same subscription, they get one invoice for all those products and makes it easy for us and for the customer.

Recurring charges

Once a subscription is setup, Stripe takes care of recurring billing. We are completely hands off for this and Stripe does a webhook call to our end point on the status of subscription renewal. Renewals do fail for several reasons - expired cards, fraud prevention, country specific restrictions etc. The simplest is to add support invoice.created and grant entitlements - if the payment goes through great. If there is an issue with payment, reach out to the customer for payment and if the payment is not received beyond certain interval clawback those entitlements and downgrade the customer to free plan.


I felt building the downgrade flow is the most complex thing in the entire system. Contrary to upgrade, when a customer is downgrading to a lower SKU, they already realized value for the higher SKU and downgrade must happen at the end of the current term. The solution for this can get complex depending on the products and how the downgrade process must be managed. In the past, we built our own system for managing such downgrades. Such system can be pretty complex, fragile and often error prone. But, what is the best way to deal with such scenarios.

Enter Subscription Schedules: A subscription schedule in Stripe allows setting up a schedule at which time certain product changes must happen in a schedule. For example: Customer has a subscription with a Paid SKU, and at the end of next month, the subscription must change to Free SKU. For achieving this scenario, create a schedule for the subscription. Add a new phase at the end of current term and add the new SKU to the phase. Stripe automatically takes care of moving the subscription to the products in the new phase at the scheduled time. Refer for an example.

Stripe has several other features and including a ready to use Portal for simple scenarios. And I am a happy Stripe customer.

Merchant of Record

Stripe is amazing and helps build a billing system easily. However selling products worldwide often introduces complexity with taxes in jurisdictions we sell in. Paddle seems to be the go to solution for reducing the complexity so Paddle would act as the Merchant of Record. So, technically we just sell to Paddle and Paddle does the selling to the real end-customer. As a company, we don't have to deal with any complexity. And Paddle takes about 5% cut in revenue for offering their service.

I contemplated using Paddle right away. However when I tried to sign up, they have "Request a free account..", which implies the signup process is not immediate and there is a request/approve process for starting with Paddle.

Paddle can be great once the company has sizable revenue and there are resources who can spend time integrating with them. But for a startup, when time is of the essence with negligible revenue in the initial years, dealing with Paddle's sales cycle, understanding their product and reviewing documentation (compared to Stripe's awesome docs) is not worth the effort. We might eventually have to use Paddle, but for now Stripe is the way to go with the available resources.**