Biller migration: how we changed our billing cycle

Baicheng Yu
The Qonto Way
Published in
9 min readMar 2, 2021

At Qonto, we charge our clients monthly for the services we provide via a service called Biller. Biller is a service that manages our clients’ subscriptions and monthly billing. A significant portion of our revenue comes from this service, so it’s a very critical service for us.

In order to improve the accounting experience for our clients, we recently changed the billing date from the anniversary date of the account creation to the beginning of month. Why did we change this, and how did we make the migration as smooth as possible?

Why did we decide to migrate the billing date?

Previously, we billed our clients the service fees on their anniversary date, and we generated one invoice for all those fees on that same date. This led to several issues for our clients and internal teams.

  • One billing cycle can span over 2 months, which makes the accounting very difficult for our clients and our internal teams. They needed to have pro-rata approach to see what had been paid each month.
Billing cycle spans over 2 months
  • No invoice was available when doing monthly closing. The clients had to wait until the anniversary date to get their invoices.
No invoice available for monthly closing

Our product team analysed over 100 Zendesk tickets regarding billing, and we realised that we needed to address these issues to improve customer satisfaction.

They also compared the different billing strategies on the market. In the end, we chose the following solution.

Target solution chosen

With the new billing solution, we changed the billing date to the first day of the month. On the new billing date, we charge recurring fees and generate the invoice for the previous month. There is no more manual prorating to do for our clients and our internal teams; they can do their monthly accounting closing without any waiting time.

The target solution seems pretty clear, right? But as you may have experienced, billing is never a simple thing. Let me share our experiences and show you how we achieved more simplicity.

What are our goals?

First of all, let’s define the goals we want to achieve.

We want to onboard all new clients on the new billing date. The only change for new clients is that we will bill them on the first of month. Other Biller features remain the same, and there is no regression.

For the existing clients, we will migrate them to the new billing date. They won’t be improperly charged. For the days they paid before the migration, we will refund them correctly.

We should make sure everything is transparent for our clients. We need to keep them informed before the migration to explain how they will be impacted and how the new billing process works.

We need to provide dedicated support for clients who may be confused about what’s happening or encountering billing issues.

We should also make sure that our billing system won’t be overwhelmed when we start to bill all clients and generate their invoices on the same day.

What did we do for the new clients?

We decided to start by applying the new billing solution to new registered clients. This is because we wanted to be sure first that our solution worked well with fresh, new accounts before we migrated all existing clients.

In order to limit the risk and side effects that we could introduce, we onboarded only an initial 10 beta clients on the new billing solution and observed how the new billing behaviours worked for them.

Thanks to the exhaustive QA we did on staging, the new billing solution worked as expected for the beta clients. We then opened it to all new clients.

Difficulties encountered in migration

It’s quite straightforward to onboard new clients. Migrating existing clients is harder. The difficulties we encountered came from different aspects.

We bill all clients on the same day. Instead of distributing traffic over one month, this concentrates traffic on one day, so we needed to make sure that our system was capable of handling this heavier load.

The scope of the project was large. The new billing solution was not a change with limited boundaries. It involved the whole billing system, from subscription management to invoice generation.

Because the scope of project is large, it was inevitable that we’d need to consider many different scenarios. We had to take into account all practical possibilities, including:

  • new clients vs. existing clients
  • monthly price plans vs prepaid price plans
  • clients with free trials vs. clients with commercial vouchers, etc.

QA is time-consuming. In order to make sure there wouldn’t be regressions in production, we have to test all different scenarios on our staging environment. Subscription billing happens only once per month, and we need to find a way to simulate the billing in a given month.

With all the difficulties mentioned above, let’s move on to the next section to see how we managed to tackle them one by one.

How did we organise our work?

First, we familiarised ourselves with the whole Biller codebase. We wrote detailed documentation to describe the current design, architecture, and orchestration.

In the tech discovery phase, we gave a presentation to the team on the current design, a comparison of different solutions we explored, and our technical proposal. We let other team members challenge our proposal.

Once we aligned ourselves with the same solution, we started to write the technical dive-in. A technical dive-in is a document that explains the “Why” and the “How” in our approach to solving functional challenges. The goals are to share knowledge across team members, encourage feedback, and avoid reworks during the delivery phase. In the meantime, it allows us to define best practices that are shared by all. A Dive-in is divided into 3 phases (Investigation, Conception, Validation). During Dive-in, we provided all the context and material needed to understand what we planned on building.

We also sliced the whole project into several parts. Depending on the complexity of each part, we wrote also a sub-Dive-in to describe our solutions in detail. In the end, we had a clear understanding and alignment on what we needed to do and how to do it. With the project slicing in each Dive-in, we had measurable tasks and an estimate of the work.

The whole development was mainly shipped by two developers. QA was led by our product manager who defined the QA plans and acceptance tests. We provided him the tools to make the QA process easier and more efficient. That way, he wouldn’t need to wait one month to get the next invoice.

How did we achieve our goal?

We anticipated the load increase in the Biller service and the Pdf service. Pdf is the service that generates invoice files as PDFs. It accepts invoice data and renders it with an HTML template, converts the HTML file to a PDF file, and sends it back to the upstream service. Rendering and converting files is a very memory-intensive task. In order to make sure that we wouldn’t overwhelm Pdf service, we did load testing before we launched the migration process. We also communicated with our SRE team to fine-tune our infrastructure resources (CPU, memory, and number of kubernetes pods).

Currently, the Biller service is processing more than 150K monthly billing jobs on the first of month. It processes more than 8K monthly billing jobs per hour along with many other billing jobs (cards, transactions, checks, etc).

Number of monthly billing jobs processed by Biller service (per hour)

The Pdf service is also generating more than 150K PDF files for clients’ invoices on the billing date. On average, it generates around 140 PDF files per minute. These numbers are increasing as we have more and more clients.

Number of invoice pdfs generated by Pdf service (per minute)

In addition to SRE team, this involved a lot of other stakeholders, such as growth, communication, data, custom success, operations, and finance teams. We sought alignment with all stakeholders before releasing anything.

The most difficult part is reimbursing clients who were billed on their last anniversary date. We must consider a different approach to refunds depending on whether:

  • the client is on a prepaid plan or monthly plan
  • the client is still in a free-trial period
  • the client ordered a card over the limit of a price plan
  • the client has an ongoing voucher
  • the client’s voucher is recurring
  • the recurrence date of the client’s voucher is before or after the client’s last billing date

I’m going to show you two examples, so you can get an idea of the complexity we faced.

Example 1: The client is on a monthly plan. The client is not in a free trial period. The client has an ongoing voucher applied before the billing date.

Example 2: The client is on a monthly plan. The client is still in a free trial period. The voucher will compensate the fee of subscription. Even if we migrate this client to the new billing date, we can’t bill them until the end of the free trial. We have to delay billing to the end of the free trial.

You can get a general idea of the difficulties we encountered. Some of these billing scenarios have the same pattern, so we can classify them into different catalogs. For each catalog, we have prepared an individual task to migrate the corresponding clients.

Based on the catalogs we produced above, we elaborated different reimbursement solutions. For each catalog, we made a query to select all corresponding clients, then calculated the amount to refund for them. We also implemented a dry-run mode in our migration task to provide an accurate refund estimate. In order for refunds to be successfully processed by our system, we built a dashboard to monitor their statuses. On September 30, we were able to reimburse our clients as planned.

Conclusion

Overall, despite its complexity, the Biller migration is a success that we achieved over the last few months. We met the goals we defined in the beginning: all clients were successfully migrated to the new billing date. We didn’t encountered any regression. There was no service degradation or downtime.

Communication is very important, both internally and externally. It allows us to be transparent with our clients, gather important information from other internal teams, and also get support from them. The exhaustive QA also played an important role; it helped us to reduce the risk of regression, especially in such a complex project. Thank you for taking time to walk through our Biller migration with me. It is just the beginning of how we are improving the accounting experiences for our clients at Qonto. More accounting features and improvements are on the way!

About Qonto

Qonto is a neobank for SMEs and freelancers founded in 2016 by Steve Anavi and Alexandre Prot. Since the launch in July 2017, Qonto has made business banking easy for more than 120,000 companies. Thanks to Qonto, business owners save time (streamlined account opening before a day-to-day user experience with unlimited history, accounting exports, expense management feature), have more control while giving their teams autonomy (real-time notifications, user right management system) and have improved visibility on cash-flows (smart dashboards, transactions auto-tagging, and cash-flow monitoring). They also enjoy stellar customer support, at a fair and transparent price.

Interested in joining a challenging and game changer company? Consult our job offers!

--

--