Day 02 Recurring Revenue

Building Recurring Revenue with Stripe Subscriptions

One-time payments are simple. Subscriptions add lifecycle complexity: trials, upgrades, downgrades, failed payments, and cancellations. Today you model a recurring product, attach it to a Customer object, and wire up the hosted Billing Portal so users can manage their own subscriptions.

~1 hour Intermediate Hands-on Precision AI Academy

Today's Objective

Stand up a Stripe Subscription with a trial period, and give subscribers access to the self-service Billing Portal to upgrade, downgrade, or cancel.

Recurring revenue changes every metric in a software business — churn rate, LTV, payback period, and investor valuation. Stripe Subscriptions handle the billing machinery so you can focus on delivering value each billing cycle rather than chasing payments.

01

The Customer Object

Stripe's Customer object is the anchor for every subscription. Create one when a user signs up, store the customer.id in your database, and attach all future subscriptions, payment methods, and invoices to it.

create_customer.js
JavaScript
const customer = await stripe.customers.create({
  email: user.email,
  name:  user.name,
  metadata: { user_id: user.id },   // link back to your DB
});

// store customer.id in your users table
await db.query(
  'UPDATE users SET stripe_customer_id = $1 WHERE id = $2',
  [customer.id, user.id]
);
One Customer per user, always. Creating duplicate Customer objects for the same user leads to split payment history, duplicate charges, and confusing support interactions.
02

Subscription Checkout with Trials

Subscription Checkout works almost identically to one-time payment Checkout — set mode: 'subscription' and point to a recurring Price instead of a one-time price.

subscription_checkout.js
JavaScript
const session = await stripe.checkout.sessions.create({
  customer: stripeCustomerId,
  payment_method_types: ['card'],
  line_items: [{ price: 'price_1234...', quantity: 1 }],
  mode: 'subscription',
  subscription_data: {
    trial_period_days: 14,
  },
  success_url: `\${DOMAIN}/dashboard?session_id={CHECKOUT_SESSION_ID}`,
  cancel_url:  `\${DOMAIN}/pricing`,
});
03

The Self-Service Billing Portal

The Billing Portal is a Stripe-hosted page where subscribers can update payment methods, change plans, and cancel. Enable it in the Stripe Dashboard → Settings → Billing → Customer Portal, then generate a session link on demand.

portal_session.js
JavaScript
const portalSession = await stripe.billingPortal.sessions.create({
  customer: stripeCustomerId,
  return_url: `\${DOMAIN}/dashboard`,
});

res.redirect(303, portalSession.url);
× Build Your Own

Custom Cancellation UI

Weeks of work. You own PCI compliance for payment method updates, must handle every plan change edge case, and rebuild every time Stripe adds a feature.

✓ Use the Portal

Stripe-Hosted Page

One API call. Stripe handles payment method updates, prorations on plan changes, cancellation timing, and the retention flow. Ships in a day.

Supporting Videos & Reading

Go deeper with these external references.

Day 2 Checkpoint

Before moving on, you should be able to answer these without looking:

Continue To Day 3
Webhooks — Reacting to Stripe Events