The week signups fell 27% and revenue hit a high
Weekend signups dropped and I went in expecting an outage. It was the seasonal downswing of the whole market, and once I measured the cohorts it turned out this was never a retention business.
Weekend signups dropped noticeably. I went in assuming something had broken, either in the product or in search traffic, and the answer was neither. The market itself was on its way down for the season, and while I was in there measuring cohorts, one of the premises of this business changed.
The app I run is a mock-test app for OPIc, the English speaking exam. You get free credits on signup, and you buy credits for AI scoring. This post starts at "why did signups fall" and ends at "what does this app actually live on". I'm writing it in the order it happened.
The first query showed a total outage
The first thing I did was pull daily signups from the database. The result was far worse than I expected. It wasn't a dip. From a certain date the signups looked almost cut off. I wondered whether the signup path had died, and for a moment I genuinely believed it was an outage.
It wasn't. The query was wrong.
This app's ORM stores DateTime as UTC without a timezone. If you put AT TIME ZONE 'Asia/Seoul' on that column, Postgres treats the value as if it were already Seoul time and converts it back to UTC. That's the opposite direction from the correct one, so the two are 18 hours apart. The most recent eighteen hours of signups slide into the previous day, today's cell looks empty, and over a few days it reads as if signups had stopped.
-- wrong: the value is timestamp (without tz), so it is treated as Seoul time and converted to UTC
created_at AT TIME ZONE 'Asia/Seoul'
-- right: it is just a UTC value plus nine hours
created_at + interval '9 hours'The embarrassing part is that I already knew this trap. I hit exactly the same thing writing a cost-aggregation query for the same app, and I wrote it down in my notes at the time. Turns out a note only works if you read it. Only after fixing the query did the real number come out.
The real number was −27%
| Period | Signups (Mon–Sat) |
|---|---|
| Sept 7 – 12 | 114 |
| Sept 14 – 19 | 83 |
A 27% drop. Not an outage, but not a number to shrug at either. At this size you usually suspect one of two things. Either search rankings slipped, or some screen broke.
So I opened Search Console. Daily clicks were 69 to 73 between September 8th and 10th, and 35 to 50 between the 13th and 17th. The same shape as signups. Rankings hadn't slipped, though. Position per page was unchanged, and it was impressions that had fallen.
Fewer impressions can mean fewer people searching. So as a third series I looked at Google Trends for 오픽, the Korean name of the exam. September 6th to 10th sat at 100, and after that it had come down to around 45.
When three series share a shape, it's the market. Looking at our own metric alone, it seems like something happened to us, but search volume itself was moving in that shape. There was nothing to fix in the app.
Five years of it looked like a blade
I stretched Trends out to five years. Search volume for the exam looks like two sharp blades. Every year it spikes in March–April and in early September, and each time it falls back to baseline within two to four weeks. The 2026 September peak was the 6th to the 10th, and the weekend where I felt "signups have dropped" was exactly the back side of that blade.
I think the driver is hiring season. The exam is offered year-round, so the question "was last week an exam week" doesn't even make sense. My guess is that application deadlines are what send people to the search bar. That's only an interpretation, though, so I can't be sure.
Then let's hold on to the people who came in September
Once you're here, there's a natural next thought. If we could hold the people who came in during the peak until the next peak in March–April, the next peak could start with returning users. That was the direction I set on the day I started the diagnosis. Raise retention, flatten the seasonality.
So I measured the cohorts. For each signup week, how many people used AI scoring at least once the following week.
The signup line climbs toward the peak while the active line stays glued to the floor. As percentages: 11%, 7%, 10%, 2%, 0%. The peak-week cohort of September 7th brought in 124 people and 3 of them used it the following week. Of the 202 people in the peak cohort from September 1st to 12th, 6 were active in the last seven days. Three percent.
That number is where I dropped the direction. Before even thinking about how to carry 3% six months forward, there was nobody to hold. Once you've sat the exam, the purpose is gone, and that's why people leave. This isn't a defect to fix but a property of the category, and with MAU or retention as the KPI I would have kept chasing the wrong thing.
It was never a retention business. So what was it?
Payment happens within three days
I pulled how many days pass between signup and the first payment.
Same day plus one to three days is 68% of the total. Only five payments took more than eight days.
68% within three days. And this lag completes the answer to the original question.
In the week of September 14th, when signups fell 27%, revenue was actually the highest yet. On web payments, 78,200 won across 10 payments. The week before, 74,700 won across 13. The cohort that came in during the peak paid a few days later, and since that lag is around three days, it landed in the following week's revenue. I found that a week where signups fall and revenue rises is simply the normal shape of this business.
So the formula shrinks to one line. Revenue is new signups during the peak, multiplied by conversion to payment within three days. Active users outside the peak don't appear in it.
Four phases, four jobs
Once it was laid out this way, the year's work split by season.
| Phase | Do | Don't |
|---|---|---|
| Rise (2–4 weeks before peak) | Prepare a deploy freeze, press the payment path for real | Big changes |
| Peak (Mar–Apr, early Sept) | Conversion only. Watch for payment and login failures | Feature releases |
| Fall (2–4 weeks after peak) | Post-mortems, stability work | Shaking the product to find a cause |
| Base (off-season) | Build SEO and store assets. They take 4–8 weeks to work, so build here | Retention improvement projects |
The most expensive item on this table is the payment check during the rise. Right before this September's peak, Android in-app payments were silently dead for ten days, and I wrote about that separately. At the time it ended as "I didn't verify". Seen from here, those ten days sat on the threshold of one of only two revenue windows in the year. The same incident costs a different amount depending on when it happens, and in this business, right before a peak is when it costs the most.
The off-season work changes too. A search asset takes four to eight weeks after you build it before it does anything. Build it during the peak and it's late. Build it during the fall and you get impatient. What gets built in October through December bears fruit in March, so I'm treating the next three months as what decides the next peak.
Not yet tested
That's the set of principles I wrote down on September 20th. To be honest, none of it has been tested even once. The next peak is March–April, so the result won't be in for half a year. If it turns out then that assets built in the off-season raised peak signups, this post was right. If not, it's a post that used seasonality as an excuse to let six months slide.
The seasonal curve is still someone else's, too. Right now Google Trends is the reference, and I have never yet confirmed the twice-a-year spike from our own signup curve. I've decided to log the three series together once a month, and I think that after the second peak passes we'll be able to read the phase without Trends.
And this was the second time on the timezone trap. It was in my notes and I stepped on it anyway, so there's no guarantee I won't step on it again. This time I left the correct query behind in a read-only script, but the problem is the day I write a new query by hand.
The next check is the first Monday of October. Until then, I've decided not to touch anything even if the numbers go down.
End