Early-stage products are all about uncertainty. With poketto.me, I started by building something I wanted to use — and gave it away for free. Then came early adopters asking for features, and eventually I began experimenting with monetizable “premium” features: personalized podcasts, news aggregation, summaries, contextualization, etc.
That third bucket quickly gave me headaches. I needed a way to put usage guardrails around these features:
👉 to separate free from premium,
👉 to distinguish “beta” from production-ready,
👉 and to keep my future monetization options open.
Following my own advice from TIL #37 (don’t bring out the big guns right away), I skipped enterprise-grade entitlement systems like ChargeBee and hacked together something simple: at first, each user got a list of entitlements (just free-text strings) that my code would check and that I could manage in a simple admin UI. ✅
That worked—until it didn’t.
As I refined the personalized podcasts, I realized a binary “Y/N” wasn’t enough. I wanted free users to create podcasts too, but with limits:
👉number of feeds,
👉max length per episode,
👉total monthly listening time.
Suddenly my simple check ballooned into quotas, both absolute (“feeds,” “episode length”) and replenishing (“minutes per month”). That meant I had to add billing periods, rollover handling, and grace logic (see Exhibit B).
Then, launch loomed. Packaging deliberations led me to three plans: Free, Premium, and Unlimited. Now my model had to support “Plans” that defined user quotas (see Exhibit C).
And of course, I still had to map all this to Stripe’s model (customers, prices, subscriptions). Not exactly plug-and-play. 😅
I got it working in the end — but in hindsight? Using a dedicated solution like RevenueCat (which integrates directly with Stripe) might have been the smarter path.