md-platform

channel-tiered-subscriptions-simplifications.md
View raw Back to list

ń# Simplifications — Channel-Tiered Subscriptions

Levers to reduce complexity on the channel-tiered-subscriptions feature, ranked by complexity-reduction-per-feature-loss. The first three are the big wins.


High-impact cuts

1. Ship web-only first; defer mobile IAP entirely

Biggest single win. Netflix and Spotify do this on iOS — users can't subscribe inside the app; they sign up on the website, and the app just recognizes the existing subscription on login. Apple explicitly allows this.

Saves:

Drops complexity: 8 → 6


2. Drop the "Livestream-only" tier

The single most expensive piece of code: real-time event-state checking, can't be cached, race conditions when broadcasts end, and only benefits one of four plans. If livestream gating is the killer feature, ship it as v2.

Drops complexity: 6 → 5


3. Use Stripe Checkout + Customer Portal

Stripe hosts:

Your backend only reacts to webhooks. Skip building any of that UI yourself.

Saves: ~1 week of frontend + backend plumbing.


Medium-impact cuts

4. Drop the 6-month plan

Standard Stripe intervals are month/year. Six months requires interval_count: 6 plumbing and a new BillingIntervalMonths field. Most SaaS offers monthly + yearly only.

If you drop this, you can use the existing PremiumPlanType enum unchanged.


5. Drop the PDF perk

Requires upload infra, signed URLs, idempotency tracking, a new EmailType, and email template work. The channel owner can email subscribers the PDF manually using Mailchimp or their own tool — they own the subscriber list anyway.

Removes: an entire mini-feature.


6. Skip "coexistence with legacy Premium" — make it a hard switch

A channel uses either the old single-tier OR the new tiered, never both. Removes a class of edge cases (user has both, upgrade collision, refund collision). Channels currently on legacy stay on legacy; new ones use tiered.


7. Hardcode the one channel for v1

The original feature request was for one specific channel. If only one channel needs it today, gate behind TieredPremiumChannelId in appsettings.json.

Skips:

Make it configurable in v2 if a second channel asks.


8. Skip the Redis cache redesign

Keep the existing binary "does this user have access to this channel?" cache. For tier-aware playback decisions, just do a DB query on the video-playback path.

Trade-off: ~5–20ms slower per video load. Optimize later if metrics show it matters.


9. Don't build trial-reminder emails

Stripe sends them automatically when enabled in the Dashboard — 7-day and 3-day before trial end. Skip the customer.subscription.trial_will_end webhook handler.


Low-impact cuts

10. Skip the refund-revocation fix

It's a known pre-existing gap, unrelated to this feature. File a separate ticket.

11. Skip CheckTrialEligibility as a separate query

Just include trialEligible: bool on the existing GetChannelTieredPlans response.


Recommended MVP

Decision MVP Eventually
Payment rails Stripe web only + Apple IAP, + Google Play
Number of plans 2 (Monthly · All + Yearly · All) + 6-month, + Livestream-only
Trial 14 days, card upfront via Stripe Checkout (same)
PDF perk Skip Add later if subscribers ask
Channel scope Hardcoded TieredPremiumChannelId config Per-channel admin toggle
Access control Reuse existing binary HasAccessAsync Add video-aware overload when livestream-only tier ships
Frontend Stripe Checkout (hosted) + Customer Portal Custom UI if needed
Webhook lifecycle Fix the $0 invoice bug + add IsTrialConverted flag (same)

MVP complexity: ~4/10 Time estimate: ~1 week of backend work + a few days of frontend integration with Stripe's hosted pages.


What this MVP actually requires

Code changes (much smaller scope)

What you don't need to build


Re-adding the cut pieces later

Every cut above is independently re-addable when there is evidence the feature is worth the cost. Approximate re-addition cost from MVP:

Add-back Cost
6-month plan ~1 day (one Stripe Price + one DB field)
PDF perk ~3 days
Livestream-only tier ~1 week (access-control rewrite + caching strategy)
Per-channel admin toggle ~2 days
Apple IAP ~1 week + App Store review
Google Play Billing ~3–5 days
Custom frontend (no Stripe Checkout) ~1 week

Why this MVP-first path is better than "build it all"

  1. Revenue flowing in 1–2 weeks instead of 4–6.
  2. Real user feedback before committing to the expensive pieces. Maybe nobody uses the livestream-only tier; maybe everyone wants the PDF.
  3. No App Store rejection risk in v1. Apple subscription review is the longest-tail risk in the original plan.
  4. Stripe Checkout handles the boring stuff correctly the first time — card validation, 3DS, retries, tax. Custom flows accumulate edge-case bugs.
  5. The existing single-tier Premium keeps working for every other channel. Zero blast radius outside the one target channel.