Price your first paid tier like a promise you can keep shipping
Your AI-built app works, friends pay compliments, and then someone asks the question that ends the honeymoon: what does it cost? Most builders answer with three tiers, a lifetime deal, and a coupon code before they have ten paying users. That is backwards. Your first paid tier has one job: turn a working demo into a promise you can keep while you keep shipping.
One price, one promise, one purchase path. Everything else — annual plans, team seats, usage meters — can wait until real customers ask for it with their wallets open.
One paid tier beats three half-priced guesses
Three tiers feel professional, but each tier multiplies every decision you have not made yet. What is gated and what is free? Which tier gets priority support? What happens at the trial boundary for each plan? With three tiers you answer those questions three times, usually inconsistently, usually in code paths you wrote at midnight.
A single paid tier collapses all of that into one clean line: free users get the demo-shaped product, paid users get the production-shaped product. Your gating logic has two states. Your paywall has one button. Your support load has one answer for "which plan fixes this."
This also keeps your store listings honest. App review teams read your paywall copy, tap through the purchase flow, and check that restore works. One tier means one flow to get right on iOS and Android. Builders who ship three tiers before their first sale usually discover that tier two was never purchasable on one platform, and they find out from a one-star review.
Start with monthly billing only. Annual discounts, lifetime deals, and regional pricing are optimization levers for a funnel that already converts. Until you have consistent weekly purchases, every extra option is a distraction from the only metric that matters: does anyone pay the single price you asked?
Anchor the price to the job, not the model bill
The most common pricing mistake in AI-built apps is passing the model bill straight through to the user with a margin on top. Your costs will move — providers reprice, you switch models, caching changes your token profile. If your price is cost-plus-tokens, every provider change becomes a repricing event and a support conversation.
Price the finished job instead. What does the user get when the task is done: an edited video, a planned trip, a clean inbox, a shipped workout week? Pick the number that feels fair for that outcome delivered reliably, then make your own costs fit inside it. That order forces the engineering discipline that matters: caching, smaller models for easy subtasks, and guardrails against runaway retries.
A practical way to sanity-check the number: write the refund sentence before you ship. "If this does not save you at least an hour a week, email us and we refund the month." If that sentence terrifies you at nine dollars a month, the product is not ready to charge for — or the price is wrong for the job it actually does. If you can stand behind it, you have a price and a quality bar in one line.
Keep the free tier genuinely usable but clearly bounded. A builder pattern that holds up well alongside entitlement-gated paywalls is letting the project structure carry the value story while the paywall carries the limit story, the same shape described in our RevenueCat entitlements guide. Free users should succeed at something small and real, then hit a limit that feels like a natural upgrade moment — more projects, longer history, export, collaboration — not a wall in the middle of their first task.
One codebase. iOS, Android, and web.
The Fitness Kit ships with auth, a database, and a backend already connected — no setup. Live demo at fitness-preview.otf-kit.dev.
Gate with entitlements, charge with checkout
Two systems, two jobs. Entitlements decide what the user can do. Checkout collects the money. When builders mix them — checking purchase receipts directly in UI code, or inventing their own subscription state — every refund, grace period, and platform quirk becomes a bug.
The shape that survives review and refunds looks like this: a single entitlement key, something like pro, owns every gate in the app. The paywall offers one tier that grants it. Everything downstream checks the entitlement, never the receipt:
// Illustrative gating shape — adapt names to your own entitlement setup.
type Entitlements = { pro: boolean };
export function canUseExport(e: Entitlements): boolean {
return e.pro === true;
}
export function paywallCopy(e: Entitlements): string {
return e.pro ? "You are on Pro." : "Upgrade to Pro to enable export.";
}Money collection belongs on a hosted checkout surface rather than in hand-rolled card forms. A hosted session keeps PCI scope, tax identifiers, and receipt handling on the provider side, and it gives you a single server webhook to fulfill against. The Checkout Sessions model in the Stripe Checkout docs is the reference for this shape — one session per purchase intent, fulfilled exactly once on the server.
That fulfillment path deserves the same care as the paywall. Webhooks arrive more than once, out of order, and during deploys. Our idempotency write-up walks through the exact failure: the same purchase event delivered four times, handled safely because fulfillment keyed on the event identity instead of blindly re-granting. Build that before your first sale, not after your first double-grant.
Trial length is a support ticket decision
Free trials convert, but every trial day is a day the user can get confused, lose a card, or forget why they signed up. Short trials with a clear end beat long trials with a vague promise — especially for apps where the core value shows in the first session.
Seven days fits most single-job apps: long enough to use the thing twice, short enough that the end date stays in memory. Fourteen days fits apps tied to a weekly rhythm. Thirty-day trials on a first paid tier are almost always a mistake — they delay your first real retention signal by a month while doubling the window for expired cards and forgotten cancellations.
Whatever you choose, make three things true from day one. First, the trial end is visible inside the app, not buried in an email. Second, cancellation takes fewer taps than signup — app review checks this, and users remember it. Third, expiry degrades gracefully: the user lands back on the free tier with their data intact, not locked out of an app holding their work hostage. That graceful landing is worth more long-term than any trial-length tweak, and it pairs directly with the single-variable testing discipline in our paywall conversion guide — change the trial or the price, never both in the same week.
State the trial terms in plain words on the paywall: length, what happens at the end, how to cancel. If you cannot explain it in two sentences, the trial design is doing marketing work that the product should be doing.
Ship the price behind a remote flag
Hard-coding your price, trial length, and paywall copy into the binary means every pricing experiment waits for app review. Put the purchase-path configuration behind values you can change without shipping: price identifier, trial days, headline, and which upsell slots are live. The binary knows how to render a paywall from those values; it never invents them.
A minimal version fits in one config object fetched at launch with sane bundled defaults so the app works offline on first open:
// Illustrative remote-paywall shape — values come from your own config backend.
type PaywallConfig = {
priceId: string;
trialDays: number;
headline: string;
showAnnualNudge: boolean;
};
const FALLBACK: PaywallConfig = {
priceId: "price_first_tier_monthly",
trialDays: 7,
headline: "Go Pro. One plan, everything unlocked.",
showAnnualNudge: false,
};
export function resolvePaywall(remote: Partial<PaywallConfig>): PaywallConfig {
return { ...FALLBACK, ...remote };
}This is the same freeze-one-variable discipline that makes paywall tests readable: the purchase path stays fixed while you change one offering detail at a time. When the first price underperforms, you adjust the remote value, watch a full week of purchases, and decide with data instead of a hotfix.
Keep an honest ownership ledger next to the pricing config. Our ownership math piece frames it well: the sticker price is the smallest part of what an app costs to run — support, refunds, review responses, and store fees all come out of that single tier at first. If the tier cannot carry a bad week of refunds and still leave room for model costs, raise the price before you add a second tier. One healthy tier funds the roadmap; two starving tiers fund arguments.
Launch with this checklist closed: one monthly tier, one entitlement key, hosted checkout, idempotent fulfillment, visible trial terms, graceful expiry, remote-configured price. That is a first paid tier you can defend in review, in support, and in your own margins — and every tier you add later inherits the machinery instead of reinventing it.
Sources
- Primary source (single verified external link): Stripe Checkout Sessions and hosted payment UIs — Stripe Checkout docs, verified live 2026-09-10.
- Internal references: entitlement-gated paywall structure (RevenueCat entitlements guide); single-variable paywall testing (paywall conversion guide); idempotent webhook fulfillment (idempotency write-up); ownership cost framing (ownership math piece).
Stop wiring. Start shipping.
- Login, database, and backend already connected — nothing to set up
- iOS + Android + web from one codebase
- AI configs pre-tuned + 40+ tested prompts included