I’ve been a user of RevenueCat for the better half of a decade. RevenueCat simplifies my interactions with the App Store with the concept of “Entitlements” — the user may gain the same level of access in your app with one of the many purchasing or subscription options; as the app, you’d only need to check if they are entitled to the access.
But my new app, Waymark, took this a step further with some custom business rules. I’ll share some thoughts and learnings in the post. But first a disclaimer: RevenueCat is the host of Shipaton, a hackathon for shipping a new app in two months. Waymark is an entrant. But this doesn’t reduce the truthfulness of anything I’ll share below.
- Anything a user unlocks would stay unlocked, even if the membership lapsed — no clawbacks.
- Exception: things unlocked with a free trial that doesn’t eventually convert would be locked.
What I borrowed
I shared that Waymark was heavily inspired by Slopes and Flighty. That is no less true when it comes to the business model. Both apps were flagship in their realm, and both got me pay happily. They quietly share the dichotomy of what’s free vs. what’s paid: Surface-level numbers are free; depth and synthesis are paid.
Translated to Waymark:
- You can see your hiking stats: distance, duration, and elevation gain, for free. The same is true for calories burned and your heart rate metrics.
- You can organize your entries however you want — rate them 1-5 stars, bookmark them, or group them into a trip — for free, too.
- Deep insights and synthesis are paid. This includes auto-detection of a rest period, the interactive chart, and the colour-coded route line and markups.
- You can import hiking activities from the past 12 months for free. To build a full history, you’d need to pay.
The premium package is an annual subscription at US$15, with a 3-day trial. There’s also a one-time purchase at US$40. Hiking is a seasonal activity, so I learned from Slopes and eschewed a monthly subscription option — fewer churning and less unhappy thoughts that I charge you every month for nothing in return.
On surface, this is all easy to implement. But I wanted to add some more play to this.
The no-clawback rule
When you pay in Slopes, your historical entries are unlocked with premium insights, too. They stay unlocked even if your subscription expires. I love this no-clawback rule, and I want it in Waymark. But it’s easier said than done with edge cases:
- If a user takes the free trial but doesn’t convert, their entries shall be locked again when trial expires.
- If a user pays, their current and past entries shall be unlocked forever, even if their subscription lapses.
- If a user pays, then asks for a refund… they are treated as a paid user for their past entries — it isn’t worth the app’s goodwill to revoke the user’s access, since it can easily backfire.
A gift entry
Any new user of Flighty gets their first flight in true unlocked experience, for free. This seems a good idea, too, for Waymark. One improvement to the logic: I cannot just let the user unlock the most recent hike, or the next hike they create. They may want to use the free credit on a great trek they did some time ago, not a walk in the park last Sunday. The act of using the free unlock needs to be intentional.
This means that the gift entry will compete with the CTA to the paywall. But it’s a bet I’d like to make: The gift entry is selling the user of what’s possible, and betting they’d come back for more.
Implementing both rules
Feature-wise, there is a dichotomy of gates: A per-entry gate that hides or displays metrics and maps and charts; and a app-level gate that prevents the user from importing old posts from more than 12 months ago.
The latter can be handled quite plainly with RevenueCat’s entitlement check. The former requires a property on the Core Data entity to remember the unlocked status for each entry, or a stamp:
- By default, the stamp is
locked. A user with active membership entitlement (either via free-trial or paid membership) sees the entry as unlocked instead. - When the user applies Gift Entry credit, the entry is stamped
gifted. This is unlocked regardless of the user’s membership status. - When the user pays for a membership, all entries are stamped
paid. A paid entry shall always have everything unlocked, regardless of the user’s entitlement.
A happy side effect this created: When a user pays for membership, their gifted entry is overwritten as paid. Upon membership expiry, the user automatically regains that gift credit. They can apply it to a new entry that they create — this provides a nice hook for membership benefits.
What the promise cost
For 10 years — PlantPal, Someday, Kodist, the list goes on — my RevenueCat integration never went past a single question. Does this user have the entitlement, right now? Never claw back can’t be answered with that, and it generated 3 requirements, each one falling out of the last.
Entitlements are about the user; the promise is about the entry. So the state had to move onto the hike itself. Every entry carries a mark saying it was earned under a paid membership, written at creation, synced through iCloud like any other field, and never revoked — not on lapse, not on refund. When someone subscribes, one backfill pass marks everything they already have. After a lapse those entries keep every per-entry Premium view; only the genuinely aggregate features, full-history import and same-trail comparison, ask for a live membership, because they can’t be attached to any one hike.
A trial that never converts can’t leave permanent marks behind. Which means it’s not enough to know that an entitlement is active — I need to know why. During the 3-day trial everything renders, including unlimited import, but nothing gets marked; the marks are applied retroactively, only if the trial converts. That closes the import-everything-and-cancel loophole while remaining an ordinary trial ending, which nobody mistakes for a claw-back. RevenueCat exposes exactly this as periodType on the entitlement — .trial against .normal. It has been sitting in the SDK the whole time, waiting for a model that needed it. I’d treated entitlements as booleans for a decade.
A lapse isn’t always a decision. Cards expire, banks decline, people are in a tent with no signal. App Store Billing Grace Period covers the involuntary kind, and it’s a checkbox in App Store Connect that RevenueCat reflects straight into the entitlement. On top of that Waymark adds its own 48-hour courtesy window after expiry, for voluntary gaps, timezone edges, and the support emails that never have to be written.
Three requirements I’d never had a reason to reach for, and RevenueCat already had all 3. That’s the factual version of the kiss-up: the tool was ahead of my requirements, not behind them.
Worth saying that the 2 weeks weren’t typing. Claude Code wrote most of the implementation, and this is the kind of work agentic coding is quietly great at — a precise spec in, precision out, plus unit tests around the edge cases I kept getting wrong on paper. The time went into deciding what the rules should be.
The bet
Which brings me back to the free entry.
There are 3 places where Waymark gives away something it could plausibly charge for. The one free unlock, no paywall shown. That unlock coming back if you delete the hike you spent it on. And the year-in-review recap, free in full, for everyone — Gentler Streak convinced me there, because their free Activity Recap is the thing people screenshot and share, and that does more marketing than a locked “detailed version” would ever earn back.
All 3 are the same wager, and I want to state the case against it fairly, because it’s a good case. Every one of them removes a moment where a user would otherwise hit a wall and decide. The free unlock in particular hands someone the exact feature they’d be paying for and then asks nothing. Anyone optimizing the funnel would remove all 3 and watch conversion go up that week.
My reasoning is that a paywall shown to someone who has never held the paid thing teaches them nothing. It asks them to buy a description. A hike that’s fully unlocked and stays that way teaches them precisely what they’d be buying, on their own data, on a trail they remember. And someone patient enough to delete and re-unlock entries one at a time to dodge US$15 was never going to convert anyway; the leniency is free goodwill.
That’s the argument. It is not evidence. Per my testing of exactly one launch, I have no idea whether it’s true, and one launch isn’t a sample size. If it’s wrong, it’s wrong in the direction I’d rather be wrong in — and I’ll post the numbers either way, with real charts, once there are enough of them to mean something.
Parting thoughts
The whole build took 3 weeks. The rules about what happens when you stop paying ate 2 of them, and I’d spend them again.
A pricing model is a promise about how your app behaves when the money stops.
Make it one you can keep without a meeting.
Until next time ✌️