You want to ship a paid course site. Videos behind a paywall, monthly subscription, the basics — like Teachable, Podia, Kajabi, or this site you're reading. The industry-standard way to build it pulls together half a dozen vendors and lands around $200/month before you have a single paying customer:
- Mux or Cloudinary for video ($1+/1k delivered minutes, plus encoding)
- AWS for the API + database (Lambda + RDS = ~$60/mo idle)
- Auth0 for login (~$35/mo at the first real tier)
- Stripe for subs (everyone uses this, it's fine)
- CDN stacked on top (CloudFront or Fastly)
There is a budget version of the same site that runs on one vendor's free tier and only starts charging meaningfully when you've got real revenue. It's the stack this site runs on, and it's the subject of this series.
The whole thesis in one line: Cloudflare gives you almost every primitive you need (compute, storage, database, KV, CDN), R2 charges $0 for egress so video bandwidth is free, and the only external services you need are Stripe (payments) and Google OAuth (sign-in). One bill, one runtime, ten dollars a month until you're profitable.
This chapter is the architecture-and-bill overview. The next three chapters deep-dive each piece: streaming on R2 (Ch 2), auth + Stripe (Ch 3), and the paywall itself (Ch 4).
The Whole Stack in One Picture
Figure 1 — Yellow boxes are Cloudflare (one vendor, one dashboard, one bill). Purple boxes are external (Stripe for money, Google for identity). That's the whole stack.
Each box is a separate chapter or section in this series and is also taught from scratch in the web series — so when you hit something you don't know, you can drop down a level:
| Piece | What it does | From-scratch tutorial |
|---|---|---|
| Worker | Your "backend" — runs JS at the edge, responds to HTTP | Web Ch 8 |
| D1 | SQLite at the edge — users, subs, progress | Web Ch 9 · Cloudflare Ch 3 |
| R2 | Object storage for videos + images (the $0-egress hero) | Web Ch 10 · Cloudflare Ch 2 |
| KV | Globally-replicated key-value cache (sessions, hot reads) | Cloudflare Ch 4 |
| Auth | Google OAuth → JWT session cookie | Web Ch 11 · Web Ch 12 |
| Stripe | Subscriptions via Payment Links + webhook | Web Ch 13 |
The web series teaches each primitive in isolation. This series shows how they snap together for one specific product: a course site.
The Five Big Architecture Calls
These are the trade-offs that shape the budget. Each is a real, defensible decision — you can swap any of them for a heavier vendor later, but you don't have to start there.
1. R2 instead of Cloudflare Stream (the budget headliner)
For video hosting, Cloudflare offers two products and they're priced very differently:
| R2 (object storage) | Stream (managed video) | |
|---|---|---|
| Storage | $0.015 / GB-month | $5 / 1,000 min stored / month |
| Delivery (bandwidth) | $0 — always | $1 / 1,000 min delivered |
| Encoding | You pre-encode locally (free, ffmpeg) | Included |
| Adaptive bitrate (HLS) | You ship MP4 or pre-render HLS | Automatic per-viewer |
| DRM / signed URLs | You build via Worker proxy | Built-in |
For a small library with modest viewership, R2 is one to two orders of magnitude cheaper. A 200 GB video library streamed 10 TB / month: ~$3 on R2 vs ~$15+ on Stream — but at TB-scale streaming or when you need real adaptive bitrate, Stream catches up and wins. Full breakdown with real numbers in Chapter 2.
2. Workers instead of Lambda + API Gateway
The serverless backend story everywhere else: AWS Lambda + API Gateway + CloudWatch. It works, but cold starts are real, debugging is its own job, and the bill at modest traffic is $30–60/month before you've done anything interesting.
Cloudflare Workers: 100,000 requests/day free, then $5/month for 10 million requests on the Paid plan, no cold starts (V8 isolates start in under 5 ms), and the same runtime for HTTP, cron, queues, and websockets. For a course site doing maybe a million requests a month, that's $5 flat. (For the full why-Workers-wins story see the Cloudflare series.)
3. D1 instead of a hosted Postgres
D1 is SQLite running on Cloudflare's edge. You get prepared statements, JOINs, transactions, migrations — actual SQL. The free tier covers 5 million row reads/day; the $5 Workers Paid plan unlocks much more.
Hosted Postgres (Supabase, Neon, RDS) is more powerful — better concurrency, JSONB, full-text, replication — but starts at $0–25/month idle and you're paying for an entire database server even when nobody's signed in. For a course site whose schema is "users, subscriptions, video progress, articles," D1 is plenty.
The exit ramp from D1 to Postgres later is small if your schema is sane. Don't over-commit to D1's quirks early; just don't reach for Postgres before you need it.
4. Stripe Payment Links instead of Apple IAP / a heavier checkout
If your courses are sold via a website, you can take payments through Stripe directly. Stripe charges around 3% per transaction. If you ever distribute through Apple's App Store, IAP forces you to use Apple's billing — about 30%. On a $10/month subscription, that's the difference between netting $9.70 and $7.00 per subscriber per month. Over a year and a thousand customers, that's a real five-figure number.
This site (and every course platform on the web) uses Stripe Payment Links — a hosted checkout URL Stripe gives you; no PCI scope, no custom UI. The Worker's only job is verifying Stripe's signed webhook on subscription events and updating D1. (See web Ch 13 for the from-scratch walkthrough, and Chapter 3 of this series for the course-specific integration.)
5. Google OAuth instead of Auth0 / Clerk / Cognito
You could pay $35+/month for Auth0 or Clerk and never write a line of auth code. Or you could implement Google OAuth in a Worker in roughly 100 lines — redirect to Google, get back an id_token, verify it, mint your own JWT session cookie. Free, no vendor, no rate limits, no migration headache later.
Auth0's pitch is "social logins, MFA, enterprise SSO, magic links" — every additional auth method you want. For a course site where everyone signs in with Google, none of that is in the critical path. (See web Ch 11 and Ch 12 for the foundation, and Chapter 3 for the course-platform wiring.)
The Bill at Three Scales
Numbers are 2026 list prices, rounded for clarity. Confirm on each vendor's pricing page before betting real money on them.
Hobbyist — 50 users, 50 GB of video, ~500 GB delivered / month
| Line item | Cost / month |
|---|---|
| Workers Free (under 100k req/day) | $0 |
| R2 storage 50 GB (after 10 GB free) | ~$0.60 |
| R2 egress (always $0) | $0 |
| D1 free tier | $0 |
| KV free tier | $0 |
| Google OAuth | $0 |
| Stripe (% of revenue, not flat) | ~3% of subs |
| Fixed monthly | ≈ $1 |
Real product — 5,000 users, 200 GB of video, 10 TB delivered / month
| Line item | Cost / month |
|---|---|
| Workers Paid ($5 base + small overage) | ~$5 |
| R2 storage 200 GB | ~$3 |
| R2 egress 10 TB (still $0) | $0 |
| D1 (included in Workers Paid for most usage) | ~$0 |
| KV reads/writes | ~$1 |
| Stripe (~3% of subs) | variable |
| Fixed monthly | ≈ $10 |
Scaling — 50,000 users, 1 TB of video, 100 TB delivered / month
| Line item | Cost / month |
|---|---|
| Workers Paid + overage | ~$15 |
| R2 storage 1 TB | ~$15 |
| R2 egress 100 TB (still $0) | $0 |
| D1 reads/writes overage | ~$10 |
| KV overage | ~$5 |
| Cloudflare Stream (if you've switched for adaptive bitrate) | ~$50–150 |
| Stripe (~3% of subs) | variable |
| Fixed monthly | ≈ $50–200 |
Graduation Triggers — When to Swap Each Piece
You shouldn't pre-emptively pay for the heavier vendor. But you should know the trip-wires:
| Piece | Swap to… | When |
|---|---|---|
| R2 + MP4 | Cloudflare Stream | You need adaptive bitrate (HLS) per-viewer at TB-scale delivery, or DRM, or signed-URL playback tokens out of the box |
| D1 | Hosted Postgres (Neon, Supabase) | JOINs on tens of millions of rows are slow; you need JSONB / full-text / read replicas |
| KV sessions | D1 sessions table (or Durable Objects) | You need to server-side-revoke a logged-in session immediately (KV is eventually consistent) |
| Worker-rendered pages | Next.js on Workers (OpenNext) or Pages | You want React, SSR, and a real frontend framework (this is in fact what simpleappshipper.com does) |
| Google OAuth only | Auth0 / Clerk | You need 5+ social providers, magic links, MFA, enterprise SSO — none of which a course site usually needs |
| Stripe Payment Links | Stripe Checkout custom integration | You need cart logic, multiple line items, custom upsells, gift purchases |
The pattern: start at the leftmost column for everything; promote a single piece when a specific feature it can't do becomes blocking. Most successful indie SaaS lives entirely in the left column.
What You Actually Need to Sign Up For
All three of the external accounts have free tiers. None requires a credit card to start hacking.
- Cloudflare — covers Workers, R2, D1, KV, Pages, DNS. One account, no card needed for the Free plan.
- Stripe — Test-mode keys work without bank approval; you can build the whole subscription flow before they ever know you exist.
- Google Cloud Console — for an OAuth Client ID. Free tier covers any course site's identity volume.
That's it. Three signups, zero dollars, and you've got every account you need to build the rest of this series end-to-end.
Mental Model — Three Sentences
- The whole stack is one vendor (Cloudflare) plus two external must-haves (Stripe for money, Google for identity) — that's why the bill stays small.
- R2's $0 egress is the budget headliner — video bandwidth, the line item that crushes everyone else's stack, is free here.
- Every box has a defensible "graduation trigger" — start at the cheap option for everything, and promote one piece only when a specific feature it can't do is blocking you.
Try It Yourself (20 Minutes)
- Open three browser tabs and create accounts: Cloudflare, Stripe (test mode), Google Cloud Console. All free.
- In the Cloudflare dashboard, create one R2 bucket, one D1 database, and one empty Worker. (Or run
wrangler initlocally.) You now have the entire backend provisioned. - In Stripe, create a test Product with a recurring price and copy the Payment Link URL. That's your subscription button.
- In Google Cloud, create an OAuth 2.0 Client ID for a "Web application" and add
http://localhost:8787/auth/google/callbackas a redirect URI. Save the client ID and secret. - Look at your bill projection on each dashboard. Notice it's $0.
Where This Lands in the Series
You've now got the full architecture map and a defensible cost model. The next three chapters fill in the implementation:
- Ch 2: Streaming Video on R2 — the upload pipeline, MP4 vs HLS, public buckets vs Worker-proxied auth, encoding cheat sheet, and the exact moment Stream beats R2.
- Ch 3: Auth + Stripe — Google OAuth in a Worker, JWT session cookies, Payment Link checkout, webhook verification, and entitlement in D1.
- Ch 4: The Paywall — server-side gates for videos and the count-based article paywall that keeps content indexed for SEO while still gating it for revenue.
Ship your apps faster
When you're ready to publish your Swift app to the App Store, Simple App Shipper handles metadata, screenshots, TestFlight, and submissions — all in one place.
Try Simple App Shipper