DEV Community

Cover image for A Free-Trial Rule Written Wrong in the Software: What to Check Before It Costs You Customers
Gabriele Pieretti
Gabriele Pieretti

Posted on Originally published at gabrielepieretti.dev

A Free-Trial Rule Written Wrong in the Software: What to Check Before It Costs You Customers

If you sell a subscription with a free trial, somewhere in the software there is a rule that decides how much a trial user can do. It looks like a trivial line. In my case that line was written with paying customers in mind, and a trial that spanned two months was worth double.

I'm telling the story because the same mistake, turned the other way, blocks a customer halfway through the trial. And a blocked trial user doesn't call support. They close the tab and try your competitor.

What happened

Miraviso, the app I built for hair salons, has a 14-day free trial. During the trial there is a cap on haircut previews, because every preview has a cost that I pay.

For subscribed salons the counter goes back to zero on the first of every month. That makes sense: they pay every month, every month they get their allowance. The problem was that the trial used the same rule. A salon that started its trial on 25 October finished it on 8 November. On 1 November the counter reset, and that salon got two full allowances instead of one.

No customer was ever going to report it, of course. And no check was looking for it, because for subscribers the rule was right.

The same mistake, the other way round

For me it cost a bit of margin. But a badly written trial rule can do worse damage, and I came close to doing some myself while fixing it.

  • The customer blocked on day five. The cap is counted on the wrong basis, for example it adds usage from an earlier period. The customer is trying the product seriously, which makes them the best lead you have, and the software tells them they're done.
  • The demo account blocked forever. I had a few trial salons with no end date, the ones I use for demos. With a single cap for the whole trial, sooner or later they would have stopped and never started again. I would have found out during a demo, in front of a salon owner.
  • The fix that slams the door. On the day you correct the rule, there are people halfway through their trial. If the count changes overnight, someone finds themselves blocked without doing anything different from the day before.
  • The right number with the wrong label. The salon dashboard said "previews this month" even for trial users. A customer who reads "month" and gets stopped after ten days thinks the software is broken.

Why nobody notices

Business rules in software are written once, at the start, when there is only one kind of customer. Then come the trial, the launch discount, the demo account, the yearly plan. Each needs a slightly different rule, and often each inherits the one already there.

The whole problem sits in one word that seems obvious. For me it was "the period". For a subscriber it meant the billing month. For a trial user it should have meant the 14 days of the trial. The software used the same word for two different things.

These mistakes only show on specific days: at the end of the month, in February, when a customer moves from trial to subscription. If nobody tests exactly those days, they sit there for months.

What to check in your software

You don't need to read the code. Sit down for half an hour with whoever wrote it and run these checks together.

  • Write the rule in one sentence. "A trial user can do at most so many things in 14 days, counted from the day they signed up." If your supplier tells it differently, you have already found something.
  • Try the awkward dates. A trial that starts on the 25th, on 28 February, on 31 December. Ask your supplier to simulate them: with an automated test it takes minutes, with no need to wait for the end of the month.
  • List your kinds of customer. On trial, subscribed, demo account, moving from trial to paid mid-month, cancelling and coming back. For each: which rule applies?
  • Look at what the customer reads. The number on their dashboard and the words next to it. They must say the same thing the rule says.
  • Ask what happens when you fix it. Do people already on trial keep the usage they have? Are they blocked overnight, or do they reach the end normally?
  • Two people at the same moment. Two employees of the same customer using the service in the same second must not be able to go over the limit together.

How I fixed it

Before touching the rule I wrote an automated test that reproduced the problem: a trial started at the end of October, a few previews, then the calendar moved to early November. The counter had to stay where it was. Right after, I wrote another one for subscribers saying the opposite: on the first of the month you start again. That way I couldn't fix the trial by breaking the subscription.

Then I changed the rule: for trial users the count runs from the first day to the last, with no reset. Usage already recorded by salons halfway through the trial stayed in the count, so nobody saw their number change overnight. Demo accounts kept the monthly count, on purpose. And the dashboard now says "in your trial" instead of "this month" for trial users.

An internal statistic that only I use still counts by month. It decides nothing for customers, and I noted it in the project notes. I preferred to leave it that way rather than widen the change.

For the technical reader

The fix had three constraints that are worth more than the bug itself. No real numbers below; the pattern is what matters.

The period is a function of the customer state. The old helper returned "the billing period if there is a subscription, otherwise the first of the current month". That definition was written for one kind of customer and then used for two. Now the helper takes the customer: trials with an end date count on a single bucket for the whole trial; subscribers and open-ended demo accounts keep the monthly bucket.

Usage already recorded must keep counting. On release day some trials already had a row for October and one for November. Changing only the key would have dropped November's usage and widened the cap for someone halfway through. So the trial counts on the bucket of the month it started in (the row the old code already wrote) plus any later rows that existed before the release.

For subscribers this changes nothing, because there are no rows in the future.

The reservation must stay atomic. Two devices of the same customer can ask at the same instant. If both read "one left", both pass. The check and the increment have to live in one statement, so the sum of later rows goes inside it, not in a read before it.

The database locks the row, checks and increments in one step; no row back means the cap is reached.

Tests first. The first commit was only a failing test: a trial started late in October, some usage, the clock moved to early November, the counter must not reset. Next to it, the opposite test for subscribers, so the fix could not break billing. The "today" function is injected, so nobody waits for the end of the month. If you run a SaaS with trials, start a fake one on the 25th and move the clock a week: about ten lines of test.

If you want to see how Miraviso is built as a whole, there is the project page. If you sell subscriptions or services with a trial and want to check that the rules in your software say what you decided, that is work we can do together, starting with a free 30-minute call.


Originally published at gabrielepieretti.dev. I write about software for small businesses, Laravel, FastAPI and privacy-by-design. More here.

Top comments (1)

Collapse
 
robertpaschal profile image
Odinaka Robert Nnamani •

A demo account with no end date is a bug that waits for the worst possible moment, mid-demo, front of the customer