TrainFlow lets coaches manage their athletes' training plans through a paid subscription. Coaches feared losing access to their athletes' data if they cancelled, so pricing alone wasn't the barrier, trust was.



What I owned
Designed the coach subscription model, paywall flow, and freeze mechanic, including three concepts rejected after corridor testing
Ran interviews and corridor tests with coaches, then rebuilt the grace period, athlete selection, and freeze duration based on the results
Results
Free to Paid conversion: 19% | Paywall to payment: 34%
Freeze to resume rate within 30 days: 38%. This confirmed freeze works as a retention mechanic, not just a soft deletion.
Removed three friction points found only after building and testing: the grace period, manual athlete selection, and the time-limited freeze.
Monetizing existing coaches beat "let's build AI Coach"
We had an internal debate: build AI Coach next, or monetize what already existed first. As a team, we scored both options using the RICE framework.
AI Coach had higher Reach. The athlete audience is three times larger than the coach audience. But Confidence was low: we hadn't validated demand for AI coaching in our niche, and we would need to build the feature from scratch. Ease was low too: it needed ML infrastructure, device data, and new UX. Subscription won, not because of audience size, but because it was more predictable. The coach interface already existed, and this type of pricing model was already proven in the market.
The real goal was not just to launch a paid subscription, but to find a way to monetize that would not break the coach's relationship with the product.

9 of 13 platforms cut off athletes with no warning
Before designing anything, I looked at the market. I reviewed 13 platforms, including TrainingPeaks, TrueCoach, CoachNow, and Final Surge.
Most competitors simply cut the connection to athletes when a subscription expires, with no warning. Only one competitor, CoachAccountable, had a freeze mechanic, capped at 30 days. Why 30 days? It was probably a technical default, not a researched decision. I decided to test that number separately.
The paywall should meet motivation, not create a barrier
Core hypothesis: a coach will not pay for a tool until they are sure it fits their process. So the paywall should appear when the coach accepts a request, not when they open settings.

The paywall opens only when the coach tries to accept a request, not before and not after.
Three hypotheses behind the design decisions:
H-1: A coach converts to paid at the moment of highest motivation: accepting a request. Not while browsing settings.
H-2: Existing coaches will not leave if the limit does not break their current workflow.
H-3: Freeze is worth more than hard deletion.

The paywall only shows the upgrade options that are relevant, not the tier the coach already owns.
Grace period looked kind, but testing said otherwise
The first version gave coaches a grace period after expiry. A banner said: "Your subscription ended. You have N days to choose a plan or select 4 athletes," with its own modal.

Concept, not shipped. The banner gave coaches a week to think it over. In testing, that's exactly what they did: they thought it over and did not pay.
In corridor testing, coaches said, "why pay now if I have a week," and put off the decision. The grace period solved a problem that did not exist, and created a real one: it delayed conversion. We removed it completely.

No banner, no grace period. The forced screen appears the moment the subscription ends.
Choosing who gets frozen felt like punishment, so we removed that choice
The first version of the forced screen asked the coach to manually pick which 4 athletes to keep active. It had a checklist and a live counter ("3 of 4 selected").

Concept, not shipped. Coaches struggled with this step in testing. Choosing who to keep active among their own athletes felt like a punishment, not a feature.
"You're making me choose between my own athletes." This was a direct quote from testing. Now the system picks automatically: the first four athletes by join date. The coach just confirms.

No selection screen at all. The system picks, and the coach just sees the result.
I also changed the button on the applicant card. Instead of "Accept request," it now says "Accept & choose plan." One tap, and it's clear what happens next.
The biggest fear turned out to be losing the athlete's data, not the price
I ran 5 interviews with coaches already using TrainFlow. The audience was around 30 people at the time, so this covered roughly 15% of it.
The biggest fear turned out to be losing the athlete's data and history when the subscription was cancelled, not the price. "I've been coaching this person for three months - if I don't renew, does it all just disappear?" came up in three of five interviews.
Second insight: coaches see the 4-athlete limit not as a restriction, but as "a free trial run under real conditions."
A one-month freeze that ends in deletion contradicted the exact fear we'd just found
The first version of freeze wasn't indefinite - it had a one-month window. Three days before it expired, the coach got a push notification and an in-app banner warning that paused athletes would be permanently removed, followed by actual deletion from the roster.

Concept, not shipped - a one-month freeze window that ends in permanent removal. This is exactly what the interviews warned against: 'what if I come back later and it's gone?
We removed the time limit entirely. Indefinite storage didn't create meaningful technical cost, and it removed the main fear from the interviews.

No countdown, no deletion - frozen athletes just wait, however long that takes
On the athlete's side, the coach shows a "Collaboration paused by coach" status - no billing details, since it's not their decision.
Reactivation restores everyone at once, not one by one
When the coach renews, every athlete who did not cancel during the freeze is automatically restored, with a push: "[CoachName] is back. Collaboration resumed." If the coach's account is deleted instead, every affected athlete gets an "ended the collaboration" message, all at once.
One subscription, three different management screens
Apple, Android, and web purchases each have their own billing rules, so the management screen honestly reflects that instead of pretending they are all the same. On iOS, it points to the App Store settings.

No countdown, no deletion - frozen athletes just wait, however long that takes
On Android, it routes to Google Play. On web, cancellation and plan changes happen directly in-app through Stripe. Each screen shows the same plan details, name, renewal date, price, but the action at the bottom matches where control actually lives on that platform.
Analytics were built in before release, not after
I worked with analysts to design the event schema before the feature shipped. Core principle: every event carries its source, since the paywall opens from five different places. Without a source field, you see total views, but not where a coach came from or why they did not pay. We did not get this right the first time. I found the gap after walking through the whole flow myself, and we added the field together.
We track key moments: paywall opened, plan selected, successful and failed payment, closed without paying, chose to stay on the free plan, subscription cancelled.
Metrics that test the hypotheses:
Free to Paid conversion: the main metric, tests whether the paywall's timing is right (H-1).
Paywall to payment: conversion broken down by source, shows which entry point works better.
Freeze to Resume rate: the share of coaches who come back after freeze, tests whether freeze works as retention (H-3).
Time to upgrade: how many days a coach thinks before the first payment.
Churn by tier: compares retention between Pro and Unlimited (H-2).
Working with the team
We worked as a cross-functional team: product designer, iOS and Android developers, backend, and QA. Before release, I walked through the entire implemented flow myself and fixed several differences from the design before launch.
Every restriction has a soft landing
We designed a model where the coach never feels punished. Hitting the limit, the request stays visible. At expiry, a forced screen gives two honest options, with no waiting period. During freeze, data stays intact indefinitely, and restoration is automatic. Monetization happens at the moment of highest motivation: accepting a request, not during passive browsing of settings.