CLAUDE LABJP
FORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as OctoberFORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as October
Articles/Claude Code
Claude Code/2026-04-20Advanced

Building a Stripe Subscription SaaS with Claude Code: Webhooks, Auth, and Production Pitfalls

A complete implementation guide for building a Stripe subscription SaaS with Claude Code on Cloudflare Workers. Covers Webhook signature verification, two-layer KV + Cookie auth, and the production pitfalls that official docs won't warn you about.

Claude Code196Stripe15SaaS15Cloudflare Workers14Webhook3subscription5payments

Premium Article

When the first successful payment notification appeared in the Stripe Dashboard, I said something out loud. After two weeks of wrestling with Claude Code to build a subscription system, it was finally working in production.

What I built was a SaaS billing system that handles monthly subscriptions and lifetime licenses simultaneously — plus per-article purchases for individual premium content. Getting the full flow working in a Cloudflare Workers environment — Stripe Checkout → Webhook → Cloudflare KV → Cookie → content access — took considerably more debugging time than I anticipated.

This article documents everything I learned. That includes the pitfalls official documentation doesn't warn you about, and the process of designing the system alongside Claude Code. I've tried to be honest about where things went wrong and why.

Design the Full Payment Flow Before Writing Any Code

The most common mistake in Stripe implementations is "let's get Checkout working first, then figure out the rest." I made exactly this mistake.

The result was Webhook handling and access control logic bolted on afterward, creating entangled code. When I asked Claude Code to refactor it, the response was essentially: "The design itself needs rethinking — refactoring won't fix the structural problem." That assessment was accurate, and heeding it saved me from a more painful rewrite later.

Before writing any implementation code, map out this six-step flow and keep it somewhere visible while you work:

  • Purchase button on the frontend → POST to /api/checkout
  • /api/checkout → Create Stripe Checkout session → Redirect user to Stripe-hosted page
  • User completes payment → Stripe fires checkout.session.completed Webhook
  • Webhook handler → Write access grant to Cloudflare KV with appropriate TTL
  • Post-payment redirect → /api/verify-session → Validate session and issue Cookie
  • Cookie → Content access control on every protected page load

Having this flow explicit before coding keeps you oriented when you're deep in implementation details. It also makes dependency ordering obvious: you can't build verify-session before you know what the Cookie format needs to contain, and you can't design the Cookie format before you know what the KV schema looks like.

Using Claude Code for Architecture Review

Before touching any implementation, I described the full flow to Claude Code and asked: "What are the risks with this design?" It surfaced two issues immediately — idempotency (what happens when Webhook events are delivered more than once) and a race condition possibility if verify-session runs before the Webhook has written to KV.

For the race condition, the solution was simple: verify-session reads from Stripe directly (using the session_id parameter) rather than relying on KV having been written yet. The Webhook and the Cookie issuance are now independent flows, not dependent on each other's completion order.

Payment systems are hard to change once they're running. Investing in design review before implementation pays dividends far beyond what it costs in time.

Centralizing Everything in pricing.ts

Every price ID, display price, and UI copy for payment flows should live in a single configuration file. If you hardcode these across components, a price change means hunting through your entire codebase. For a system with multiple currencies and plan types, this discipline pays off almost immediately.

// src/config/pricing.ts
 
export const STRIPE_PRICE_IDS = {
  ja: {
    tip: "price_xxxxxxxxxxxx",     // ¥150
    article: "price_yyyyyyyyyyyy", // ¥250 (per-article)
    pro: "price_zzzzzzzzzzzz",     // ¥580/month
    premium: "price_wwwwwwwwwwww", // ¥2,480 (lifetime)
  },
  en: {
    tip: "price_aaaaaaaaaaaa",
    article: "price_bbbbbbbbbbbb",
    pro: "price_cccccccccccc",
    premium: "price_dddddddddddd",
  },
} as const;
 
// Works around the as const indexing limitation
export const getPriceIds = (locale: string) => {
  const key = locale === "ja" ? "ja" : "en";
  return STRIPE_PRICE_IDS[key];
};
 
// Co-locate CTA text with pricing — both change together
export const ARTICLE_LABELS = {
  ja: {
    heading: "この記事の全文を読む",
    description: "詳細な実装コードと解説の続きをご覧ください",
    button: "¥250 で購入",
    separator: "または",
    membershipText: "月額メンバーシップで全記事を読み放題",
  },
  en: {
    heading: "Read the Full Article",
    description: "Access the complete implementation code and detailed explanations",
    button: "Buy for $1.75",
    separator: "or",
    membershipText: "Get unlimited access with a monthly membership",
  },
};
 
// Helper for unit amounts (Stripe uses smallest currency unit)
export const getUnitAmount = (planType: string, locale: string): number => {
  const amounts: Record<string, Record<string, number>> = {
    ja: { tip: 150, article: 250, pro: 580, premium: 2480 },
    en: { tip: 150, article: 175, pro: 500, premium: 1500 }, // in cents
  };
  return amounts[locale === "ja" ? "ja" : "en"][planType] ?? 0;
};

The as const Indexing Trap

Defining STRIPE_PRICE_IDS as const makes TypeScript infer the most specific type possible, which is exactly what you want for type safety. But it means you can't index it with a plain string variable.

// ❌ TypeScript error — string can't index an as const type
const priceId = STRIPE_PRICE_IDS[locale].premium;
 
// ✅ Use the helper function (handles the type narrowing internally)
const priceId = getPriceIds(locale).premium;
 
// ✅ For server components, a typed intermediate constant also works
const PRICE_IDS: Record<string, { tip: string; article: string; pro: string; premium: string }> = STRIPE_PRICE_IDS;
const priceId = PRICE_IDS[locale]?.premium;

When I described this problem to Claude Code ("I have an as const object and TypeScript won't let me index it with a string-typed variable"), it identified the pattern immediately and explained both approaches — which to use in a server component versus a client component, and why.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
How to wire the full Checkout → Webhook → KV → Cookie billing flow on Cloudflare Workers, step by step
Production-only pitfalls — signature verification, timeouts, duplicate delivery, and event reordering — each with concrete fix code
A two-layer KV + Cookie access-control pattern that preserves deny-by-default during outages
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Claude Code2026-05-03
Claude × Stripe Meter Events — Building a Usage-Based SaaS
A production-ready architecture and full implementation for billing Claude API token consumption through Stripe Meter Events — covering idempotency, usage caps, and a hybrid base + overage pricing model.
Claude Code2026-03-21
NemoClaw × Claude — Automating Revenue Pipelines with Enterprise AI Agents
A practical guide to revenue automation with NVIDIA NemoClaw and Claude Code / Claude API. Covers agent design, API orchestration, automated content generation, and SaaS backend architecture for building self-running revenue pipelines.
Claude Code2026-05-05
Building a Recurring Revenue Freelance Business with Claude Code — A 6-Month Roadmap to ¥1M MRR
Transform your freelance dev business from per-project income to predictable monthly recurring revenue. Learn how to pitch retainer contracts, price Claude Code's productivity gains correctly, and build a client management system that scales to ¥1M MRR.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →