One subscriptions row, two stores: Stripe and Google Play in Next.js + Supabase
MotionLab sells one Pro plan through two checkouts. On the web it's Stripe Checkout. On Android it's Google Play Billing. Two stores with two lifecycles and two kinds of IDs, plus two ways of telling you something changed. The web app doesn't care about any of that. It wants one answer: is this user Pro right now? We're building MotionLab , personalized stretching and mobility sessions. Earlier…
MotionLab offers personalized stretching and mobility sessions through a single subscriptions row in Supabase. The row is keyed by the user ID and contains status, interval, Stripe customer ID, Stripe subscription ID, Stripe price ID, current period end, start date, cancel at period end, and updated date. The status column uses Stripe's vocabulary such as active, trialing, past_due, and canceled.
The interval column is either month or year. The user ID appears twice in the metadata: once in the Checkout Session and once in the Subscription itself. This allows later events to identify the user and track changes like renewals, plan changes, cancellations, and failed payments. The webhook receives the raw body and signs the exact bytes sent by Stripe to verify the signature.
The Checkout route creates the session with the user ID in the metadata, and the webhook reads the raw body to ensure signature verification.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.