Skip to main content
RapidDev - Software Development Agency
bubble-tutorial

How to Build Subscription Plans in Bubble

Building subscription plans in Bubble involves creating a pricing table UI, handling plan selection and upgrade flows, and displaying the current plan status in user settings. This tutorial covers designing a Plan Option Set with pricing tiers, building a responsive pricing table page, connecting plan selection to Stripe for payment, and showing users their current plan with upgrade and downgrade options.

What you'll learn

  • How to design plan tiers using Option Sets
  • How to build a professional pricing table UI
  • How to handle plan selection and Stripe checkout integration
  • How to display current plan and manage upgrades in user settings
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner6 min read25-30 minAll Bubble plansMarch 2026RapidDev Engineering Team
TL;DR

Building subscription plans in Bubble involves creating a pricing table UI, handling plan selection and upgrade flows, and displaying the current plan status in user settings. This tutorial covers designing a Plan Option Set with pricing tiers, building a responsive pricing table page, connecting plan selection to Stripe for payment, and showing users their current plan with upgrade and downgrade options.

Overview: Subscription Plans in Bubble

This tutorial walks you through building the subscription plan experience in your Bubble app, from the pricing page to account management. You will design plan tiers, build the pricing table, and handle the plan lifecycle.

Prerequisites

  • A Bubble app on any plan
  • A Stripe account configured with subscription products
  • The Stripe plugin installed or API Connector set up
  • Basic understanding of Option Sets and Conditional formatting

Step-by-step guide

1

Design plan tiers using an Option Set

Go to the Data tab and create an Option Set called 'SubscriptionPlan'. Add options for each tier: Free, Pro, Business. Add attributes to each option: price_monthly (number), price_yearly (number), features (list of texts — each feature as a string), stripe_price_id_monthly (text), stripe_price_id_yearly (text), is_popular (yes/no — to highlight recommended plan), and display_order (number). This keeps all plan data in a fast-loading Option Set rather than the database.

Expected result: A SubscriptionPlan Option Set contains all plan tiers with pricing and feature information.

2

Build the pricing table UI

Create a pricing page with a monthly/yearly toggle at the top using two buttons or a toggle switch that sets a custom state 'billing_period' to 'monthly' or 'yearly'. Below it, add a Repeating Group with type SubscriptionPlan (Option Set), sorted by display_order. Each cell shows the plan name, price (conditional on billing_period state), feature list displayed in a nested Repeating Group of the features attribute, and a Select Plan button. Add conditional styling: when is_popular is yes, add a border color and 'Most Popular' badge. Add conditional on the Select Plan button: when plan = Current User's current_plan, change text to 'Current Plan' and make it not clickable.

Expected result: A professional pricing table displays all plans with monthly/yearly toggle and current plan indication.

3

Handle plan selection and Stripe checkout

When the Select Plan button is clicked, start the Stripe checkout flow. If using the Stripe plugin, add the 'Stripe Checkout' action with the appropriate stripe_price_id based on the selected plan and billing period. If using the API Connector, create a Stripe Checkout Session via POST to /v1/checkout/sessions with the price ID, success_url, and cancel_url. After successful payment, Stripe redirects to your success page where you update the User's plan. Add a field to User called 'subscription_plan' (type: SubscriptionPlan Option Set) and 'stripe_customer_id' (text).

Expected result: Clicking a plan button initiates Stripe checkout and updates the user's plan on success.

4

Display current plan in user settings

Create an account settings section showing the user's current subscription. Display the plan name, price, next billing date (from Stripe data), and features included. Add an 'Upgrade' button that links to the pricing page, and a 'Cancel Subscription' button that triggers a Stripe subscription cancellation workflow. Show a plan comparison highlighting what the user gains by upgrading. Use conditional visibility to hide upgrade button when on the highest tier and hide cancel when on the Free tier.

Expected result: Users can view their current plan details and access upgrade or cancellation options.

5

Set up Stripe webhook for subscription events

Create a backend workflow to receive Stripe webhooks. Enable Backend workflows in Settings → API, then create an exposed workflow called 'stripe_webhook'. Configure Stripe to send events to this URL. Handle key events: checkout.session.completed (set user's plan), customer.subscription.updated (handle plan changes), customer.subscription.deleted (revert to Free plan), and invoice.payment_failed (notify user of failed payment). Each event looks up the user by stripe_customer_id and updates their subscription_plan field accordingly.

Pro tip: Always verify the Stripe webhook signature to prevent spoofed events from modifying user subscriptions.

Expected result: Stripe events automatically update user subscription status in your Bubble database.

Complete working example

Workflow summary
1SUBSCRIPTION PLAN SYSTEM SUMMARY
2=====================================
3
4OPTION SET:
5 SubscriptionPlan: Free, Pro, Business
6 Attributes: price_monthly, price_yearly,
7 features (list), stripe_price_id_monthly,
8 stripe_price_id_yearly, is_popular, display_order
9
10PRICING PAGE:
11 Toggle: monthly / yearly (custom state)
12 RG: SubscriptionPlan sorted by display_order
13 Cell: plan name, price (conditional), features,
14 Select button
15 Popular plan: border + badge
16 Current plan: button shows 'Current Plan'
17
18CHECKOUT FLOW:
19 Select Plan Stripe Checkout
20 price = plan's stripe_price_id
21 success_url = /success?session={id}
22 cancel_url = /pricing
23 Success page:
24 Retrieve session Update User's plan
25
26USER FIELDS:
27 subscription_plan (SubscriptionPlan)
28 stripe_customer_id (text)
29 subscription_status (text)
30
31ACCOUNT SETTINGS:
32 Current plan display
33 Upgrade button pricing page
34 Cancel button Stripe cancellation
35 Next billing date from Stripe
36
37WEBHOOK HANDLING:
38 checkout.session.completed Set plan
39 subscription.updated Update plan
40 subscription.deleted Revert to Free
41 invoice.payment_failed Notify user

Common mistakes when building Subscription Plans in Bubble

Why it's a problem: Storing plan data in the database instead of an Option Set

How to avoid: Use an Option Set for plan definitions. Only store the user's selected plan reference on the User record.

Why it's a problem: Not handling failed payments and subscription cancellations

How to avoid: Set up Stripe webhooks for invoice.payment_failed and subscription.deleted events to update user status

Why it's a problem: Allowing users to access premium features without checking their plan

How to avoid: Add plan-checking conditions on every premium feature and page, redirecting free users to the pricing page

Best practices

  • Use Option Sets for plan definitions for fast, zero-WU loading
  • Highlight the most popular plan to guide user choice
  • Show a monthly/yearly toggle with savings percentage for yearly plans
  • Always handle Stripe webhooks for subscription lifecycle events
  • Check user plan status before showing any premium features
  • Provide clear upgrade and downgrade paths in account settings
  • Test the full subscription flow in Stripe test mode before going live

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I want to build a pricing page with three subscription tiers in my Bubble.io app connected to Stripe. How do I design the pricing table and handle plan changes?

Bubble Prompt

Help me build a subscription system with a pricing table showing Free, Pro, and Business plans with monthly/yearly toggle, Stripe checkout integration, and plan management in user settings.

Frequently asked questions

Can I offer a free trial period?

Yes. Configure trial periods in Stripe when creating your subscription prices. Stripe handles the trial automatically and charges after it expires.

How do I gate features by plan?

Add conditions on premium elements and pages: visible or accessible only when Current User's subscription_plan is Pro or higher.

Can users switch between monthly and yearly billing?

Yes. Use Stripe's subscription update API to change the price. Handle prorated charges in your Stripe configuration.

What happens if a payment fails?

Stripe retries failed payments according to your retry settings. Use the invoice.payment_failed webhook to notify the user and optionally restrict access after repeated failures.

Do I need a paid Bubble plan for subscriptions?

The pricing page and Option Sets work on Free, but Stripe webhooks require backend workflows which need a paid Bubble plan.

Can RapidDev help set up subscription billing?

Yes. RapidDev can implement complete subscription billing systems in Bubble including Stripe integration, plan management, feature gating, and revenue analytics dashboards.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.