Skip to content

Subscriptions

Paid subscriptions in Now Playing unlock Pro features. Payment processing runs through PayPal, and entitlement (what features a user has access to) is managed by a dedicated subscription service that talks to PayPal and updates the user’s roles.

Browser ──► Next.js web ──► Subscription service ──► PayPal API
PostgreSQL
RBAC roles
  • Browser — runs the PayPal JavaScript SDK to show an embedded checkout widget. The user never leaves the Now Playing dashboard.
  • Web (Next.js) — thin API routes that authenticate the user, then proxy to the subscription service.
  • Subscription service (Python) — handles all the business logic: PayPal API calls, webhook processing, discount codes, scheduled jobs, and role management.
  • PostgreSQL — stores subscription state, payment history, and user roles.
  • PayPal — source of truth for payments and invoices.

This split keeps the web app simple (auth + proxy) and isolates the stateful parts (talking to PayPal, handling webhooks) in a service that can run on its own schedule.

  1. Subscribe. The user picks a plan in the dashboard. PayPal’s embedded checkout collects payment details. On success, PayPal returns a subscription ID.
  2. Activate. The subscription service records the subscription in the database and grants the user the pro role through the role-based access control system.
  3. Renew. PayPal charges the user automatically each billing period. A webhook notifies the subscription service, which records the payment.
  4. Cancel. The user can cancel at any time. The subscription remains active through the end of the current billing period, then lapses.
  5. Lapse. When the billing period ends without renewal, the subscription service revokes the pro role.

Pro features are gated through roles in the RBAC system:

RoleMeaning
proActive paid subscription
lifetimePermanent access (granted manually)
staffNow Playing team member with elevated access

When a feature needs to check entitlement, it asks the RBAC system whether the userId has the required role. The role check is cheap — it is a single database lookup backed by a Redis cache.

Discount codes can be validated by the subscription service and applied at checkout. Validation happens server-side, so there is no way to fake a code from the browser. Applied discounts are recorded as part of the subscription record.

Invoices are tracked in PayPal, not recreated locally. When a user wants to view their payment history, the subscription service fetches the invoice list from PayPal’s API on demand. This keeps accounting records consistent with what PayPal has on file.

For partners, contest winners, or compensated comp accounts, staff can grant the pro or lifetime role directly without going through PayPal. These grants bypass the subscription lifecycle and stay in place until manually revoked.

If a scheduled renewal payment fails:

  1. PayPal retries the payment according to its standard retry schedule.
  2. The subscription service waits out the grace period before taking action.
  3. If PayPal ultimately fails the renewal, the subscription is marked past_due and then cancelled, and the pro role is revoked.

The user is notified at each step so they have a chance to update their payment method before losing access.

PayPal’s Subscriptions API handles recurring billing, tax collection in applicable regions, and invoicing — removing a large compliance and accounting surface from Now Playing’s own codebase. The embedded checkout experience (via the PayPal JS SDK) keeps the user inside the Now Playing dashboard, so the flow feels native.