What Marcus includes for SaaS billing
When you tell Marcus you're building a SaaS with subscriptions, it sets up the full stack: user sign-up and login, workspace or tenant isolation so customers only see their own data, Stripe Checkout integration for payment collection, and webhook endpoints that listen for subscription lifecycle events like renewals, cancellations, and payment failures.
The generated codebase also includes an admin dashboard where you can view active subscriptions, manually adjust user status, and send transactional emails for things like welcome messages, payment receipts, and failed-payment alerts. All of this is wired together so a new subscriber can sign up, pay, and immediately access their account without you touching the backend.
Marcus defaults to hosted infrastructure in the EU, meaning Stripe webhooks hit your European endpoint and customer payment data never leaves the region unless you configure otherwise. This keeps compliance simpler for GDPR-sensitive projects.
Authentication and multi-tenancy
Every SaaS needs secure login and data isolation. Marcus generates a session-based authentication system with password hashing, email verification, and optional two-factor authentication if you specify it. Each user is associated with a workspace or organization record, and database queries are scoped so customers can only read and write their own data.
If you need team accounts where multiple users share one subscription, Marcus can model that: one billing entity with role-based permissions for team members. The generated schema includes foreign keys and access-control logic, so inviting a colleague to your workspace doesn't expose another customer's records.
Stripe Checkout and subscriptions
Marcus integrates Stripe Checkout, not raw card forms, because Checkout handles PCI compliance, localization, and mobile layout for you. The builder generates routes that create a Checkout session with your product and price IDs, redirect the user to Stripe's hosted page, then handle the success callback to activate the subscription in your database.
You bring your own Stripe account and configure your product catalog in the Stripe Dashboard—monthly plans, annual discounts, trial periods. Marcus reads those price IDs from environment variables and uses them when initializing sessions. If you later add a new tier or change pricing, you update the Stripe Dashboard and the environment config; no code rebuild required.
Subscription status lives in your database, synced by webhooks. When Stripe sends invoice.paid, the webhook updates the user's subscription end date and active status. When customer.subscription.deleted arrives, access is revoked. Marcus writes these handlers so status stays accurate even if a customer updates their card or cancels through the Stripe billing portal.
Webhook handling and retry logic
Webhooks are how Stripe tells your app about events that happen outside your request loop—a renewal charge succeeds at 2 AM, a card expires, a dispute is filed. Marcus generates a dedicated webhook endpoint that verifies Stripe's signature, parses the event type, and runs the appropriate database update or email trigger.
Because webhooks can arrive out of order or get retried, the handler is idempotent: processing the same invoice.paid event twice won't double-credit a user. Marcus also logs every webhook to a database table so you can audit what happened and replay events if something breaks during an outage.
Stripe retries failed webhooks with exponential backoff for up to three days. If your server is down for an hour, you won't lose subscription state—events will queue and replay once you're back online. Marcus doesn't add extra retry middleware because Stripe already handles it reliably.
Admin console and transactional email
The generated admin dashboard lists all users, their subscription tier, renewal dates, and payment status. You can manually mark an account as active or paused, useful for customer-service edge cases like granting temporary access during a billing dispute. The console also shows recent webhook events and failed payments, so you spot problems before customers complain.
Marcus wires in transactional email using an SMTP provider you configure—Postmark, SendGrid, Amazon SES. When a new user completes checkout, they receive a welcome email with login credentials or next steps. When a payment fails, an automated reminder goes out with a link to update their card. When a subscription cancels, a farewell email confirms the end date and offers to export their data.
Email templates are simple HTML stored in your project, so you can tweak copy and branding without redeploying code. Marcus doesn't use a complex email-builder UI—just editable template files and a sending function that substitutes variables like the customer's name and renewal date.
Edge cases: usage-based metering and complex pricing
If your SaaS charges per API call, per gigabyte, or per active seat, you need usage-based billing. Stripe supports metered pricing, but Marcus doesn't auto-generate the metering instrumentation—counting events and reporting them to Stripe's usage API is too domain-specific. You'll need to add metering code yourself: track the billable action in your app, batch the counts, and call stripe.subscriptionItems.createUsageRecord at the end of each billing period.
Similarly, if you want tiered pricing with feature gates that unlock at higher plans, Marcus scaffolds the subscription-status checks but won't know which features map to which tiers. You define those rules in your codebase—checking the subscription tier field before allowing advanced exports or team collaboration. The structure is there; the business logic is yours to write.
Complex proration scenarios—switching mid-cycle from monthly to annual, or upgrading from a 5-seat to a 10-seat plan—are handled by Stripe's proration system, but you need to decide when to allow changes and how to present the prorated invoice to the user. Marcus gives you the webhook plumbing; you add the UI and the "change plan" workflow that calls stripe.subscriptions.update.
What you still own
Marcus delivers a working subscription system, but you're responsible for your Stripe configuration: creating products, setting prices, enabling the customer billing portal, configuring tax collection if you operate in VAT or sales-tax jurisdictions. The builder assumes you'll log into Stripe and configure those settings; it doesn't provision them via API.
You also own compliance and legal: privacy policy, terms of service, refund policy, cookie banners if you track users. Marcus generates the technical infrastructure; you write the legal copy and link it from your footer. If you need automatic tax calculation, enable Stripe Tax in your dashboard and Marcus will pass the session mode that respects it, but setting up tax nexus and rates is your task.
Finally, if your SaaS scales to thousands of concurrent users, you'll need to tune database indexes, caching, and rate limits. Marcus gives you a clean starting schema and queries, but performance optimization at high traffic is outside the scope of the initial build. The code is yours to profile and optimize.