●SDK58 — The Expo SDK 58 beta is open. It ships the React Native 0.88 release candidate, and the beta period is stated as three to four weeks●11/01 — For anyone who requested an extension, Google Play's target API deadline lands on November 1. Forty-four days out●EASENV — A long-open report: secrets handed to a local build arrive as the literal variable name rather than its value, and the damage surfaces much later●NEW — The replacement the table recommended had already shut down. A record of reconciling all 74 rows of the deprecation list●UISCENE — iOS 27 requires the new scene lifecycle. SDK 57 makes it something you opt into; it only becomes the default in 58●CREDIT — What "AI errors don't cost credits" actually covers becomes clear once you record a day of asking for the same fix more than once●SDK58 — The Expo SDK 58 beta is open. It ships the React Native 0.88 release candidate, and the beta period is stated as three to four weeks●11/01 — For anyone who requested an extension, Google Play's target API deadline lands on November 1. Forty-four days out●EASENV — A long-open report: secrets handed to a local build arrive as the literal variable name rather than its value, and the damage surfaces much later●NEW — The replacement the table recommended had already shut down. A record of reconciling all 74 rows of the deprecation list●UISCENE — iOS 27 requires the new scene lifecycle. SDK 57 makes it something you opt into; it only becomes the default in 58●CREDIT — What "AI errors don't cost credits" actually covers becomes clear once you record a day of asking for the same fix more than once
Monetizing a Rork AI App: Pricing Backwards from Your Cost of Goods
How to design pricing for a Rork-built AI app by starting from per-user API cost rather than revenue. Covers the margin math behind freemium, subscription and credit models, a RevenueCat paywall in Expo, graceful quota handling, and the five metrics worth checking weekly.
There was a month where subscription revenue grew and the money left over did not.
RevenueCat showed MRR climbing. But once the Gemini API invoice and the App Store commission were subtracted, the increase had evaporated. I had been chasing revenue while quietly growing cost of goods at the same rate.
That is the thing that makes AI apps different from the ad-supported apps I built before. With a conventional app, one more user costs essentially nothing. With an AI app, every additional user carries a marginal cost — and your most enthusiastic users are the ones losing you money.
So pricing design has to start from the wrong end of the spreadsheet. Not "what can I charge?" but "what does one active user cost me per month?" What follows is how I work backwards from that number for Rork-built AI apps: the model comparison, the RevenueCat implementation, quota handling, and the metrics I actually check.
Measure per-user AI cost before you price anything
Before setting a price, find out what one active user consumes in API calls per month.
This is not hard to instrument. Log the model name, input and output token counts, and the user ID immediately before each AI call. In a Rork-generated app, the fastest route is a single wrapper function that every AI call passes through.
// lib/aiClient.ts — every AI call goes through heretype UsageLog = { userId: string; model: string; inputTokens: number; outputTokens: number; costUsd: number;};// Price per 1M tokens — replace with your actual model ratesconst PRICE_PER_M = { 'flash': { input: 0.075, output: 0.30 }, 'pro': { input: 1.25, output: 5.00 },} as const;export async function callAi( userId: string, model: keyof typeof PRICE_PER_M, prompt: string,) { const res = await generate(model, prompt); // your actual SDK call const p = PRICE_PER_M[model]; const costUsd = (res.inputTokens / 1_000_000) * p.input + (res.outputTokens / 1_000_000) * p.output; await recordUsage({ userId, model, inputTokens: res.inputTokens, outputTokens: res.outputTokens, costUsd, } satisfies UsageLog); return res;}
Why store this per call rather than per month? Because two later decisions — how you handle users who hit their quota, and how you detect churn risk — both read from this same table. A monthly invoice total tells you nothing about who spent it. Per-user data tends to reveal that the top 5% of users account for most of your cost.
After a week of logs, calculate the median and the 90th percentile of monthly cost among paying users. Those two numbers anchor your pricing. Price against the median and you go underwater in any month that attracts heavy users. Price against the 90th percentile and you are safe but expensive. In practice I land between the two, closer to the 90th.
Compare the three models by who absorbs cost volatility
There is no shortage of writing about freemium versus subscription versus usage-based pricing. For AI apps specifically, the clarifying question turned out to be simpler: whose problem is it when usage spikes?
Model
Who absorbs cost volatility
Best fit
Typical gross margin
Freemium
You — the entire free tier is out of pocket
Cheap per-call work: resizing, short summaries
50–70%
Subscription
You, unless you cap usage
Predictable frequency; daily-habit apps
60–80%
Credits
The user — they pay for what they consume
Expensive per-call work: video, batch processing
75–85%
Those margin figures are net of both store commission (15% for most indie developers on the Small Business Program) and AI cost of goods.
I settled on a subscription base with credits layered on top for the expensive operations. Subscription alone let heavy users eat the margin; credits alone suppressed first-time conversion, because "I don't know what this will cost me" is a real psychological barrier. Selling the reassurance of a flat monthly rate, then metering only the operations that spike, covers both weaknesses.
Actual price points for AI apps are not unusual:
Tier
Monthly (US)
What it includes
Lite
$4.99–$9.99
Higher limits on core features
Standard
$9.99–$19.99
Full features, higher-quality model
Pro
$29.99–$49.99
Business use, export, API access
Annual plans are usually priced at 50–60% of twelve monthly payments. Annual subscribers churn less and pay you sooner. One caveat specific to AI apps: you collect annual revenue up front but incur the cost over twelve months, so a strong annual month can flatter your cash position more than your margins deserve.
✦
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
✦The formula for real LTV after AI cost of goods, and the CAC ceiling it implies
✦RevenueCat + Expo code that degrades quality at quota instead of blocking the user
✦Five weekly metrics — including gross margin and ARPU-to-COGS ratio — with concrete thresholds
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.
"Make the free tier genuinely useful but clearly limited" is sound advice, and AI adds a constraint to it. Every bit of free tier you extend is cost you absorb for users who may never convert.
So I stopped gating on the number of uses and started gating on quality instead.
Gating approach
Monthly cost per free user
Experience
Usage cap (3/day, top-tier model)
High — premium rate × ~90 calls
Good, then a wall
Quality cap (generous limits, lightweight model)
Low — cheap rate × calls
Keeps working; the gap becomes the pitch
Routing the free tier to a lightweight model drops cost by roughly an order of magnitude. Paid plans then switch to the stronger model, so users experience the difference directly: same input, visibly better output. Someone stopped by a usage cap leaves frustrated. Someone who has seen the quality gap has a reason to pay.
What keeps a paywall out of review trouble
Two patterns reliably cause problems in App Store review:
Requiring account creation before users can touch basic functionality
Forcing a subscription without offering any meaningful core feature
These are fine:
Feature limits after a trial period (freemium)
Tiers based on AI call volume or output quality
Restricting access to genuinely premium features and content
Quality-based gating sits safely inside those lines, since the core feature itself remains free. Separately, deferring account creation until the user tries to save a result — rather than demanding it at launch — lowered both review risk and first-session drop-off.
Implementing the paywall with RevenueCat
Rork generates Expo-based apps, so the RevenueCat React Native SDK drops in directly. It handles App Store and Google Play billing plus receipt validation, which is more reliable than rolling your own as a solo developer.
// Basic RevenueCat implementation (Expo / React Native)import Purchases from 'react-native-purchases';await Purchases.configure({ apiKey: 'YOUR_REVENUECAT_API_KEY' });const offerings = await Purchases.getOfferings();const packages = offerings.current?.availablePackages;const purchasePackage = async (pkg) => { try { const { customerInfo } = await Purchases.purchasePackage(pkg); if (customerInfo.entitlements.active['premium']) { enablePremiumFeatures(); } } catch (error) { if (error.userCancelled) return; // a dismissed sheet is not an error console.error('Purchase failed:', error); }};
The early return on error.userCancelled matters more than it looks. Treat a dismissed purchase sheet as an error and you show an alert to someone who simply changed their mind — which is a good way to make sure they never open the sheet again.
Degrade at quota instead of blocking
Returning "You've reached your limit. Upgrade to Premium." is the easiest thing to implement and close to the worst thing to experience. From the user's side, you interrupted their work to ask for money.
The alternative is to fall back to the cheaper model, still return a result, and show them the difference.
// lib/quota.ts — degrade quality at quota rather than blockingexport async function generateWithQuota(userId: string, prompt: string) { const { isPro, usedThisMonth, limit } = await getQuota(userId); if (isPro) { return { result: await callAi(userId, 'pro', prompt), degraded: false }; } if (usedThisMonth < limit) { return { result: await callAi(userId, 'pro', prompt), degraded: false }; } // Over quota: return a result from the cheaper model instead of failing const result = await callAi(userId, 'flash', prompt); return { result, degraded: true };}
In the UI, show a quiet banner beneath the result only when degraded is true: one line explaining that this was generated in lightweight mode, plus a link back to full quality.
Degrade, don't block. Conversions triggered by hitting the quota went up noticeably after this change, and the reason seems straightforward. A blocked user concludes the app doesn't work and closes it. A user looking at a slightly worse result wants the good one back. The first is churn; the second is intent to buy.
Take the organic search traffic first
Before spending on ads, exhaust what App Store search will give you for free.
Your app name (30 characters) should be your brand plus one or two high-value keywords. The subtitle (30 characters) should state a benefit, not a feature. The keyword field (100 characters) takes nouns only, comma-separated, no spaces — every space you type is a character wasted.
Target mid-volume, lower-competition terms. Useful sources: App Store search suggestions, words that recur in competitor reviews, and tools like AppFollow or Sensor Tower. For AI apps specifically, the word "AI" itself is too contested to win, so it pays to bid your attention toward the problem being solved — "background remover," "meeting transcription" — instead.
Screenshots are the third-biggest factor in the download decision after icon and name. Lead with your single strongest value proposition, follow with two or three feature walkthroughs, then before/after or proof. Caption every image; plenty of people scroll the gallery without ever tapping into the preview.
Run the numbers before you run ads
The figure to calculate before buying traffic is LTV after AI cost of goods. Use revenue instead and your CAC ceiling will be badly wrong.
Monthly subscription: $7.99
Average retention: 6 months
Revenue LTV = 7.99 × 6 = $47.94
Less store fee 15% = $40.75
Less AI COGS ($1.70/user/month × 6) = $30.55 ← real LTV
Target CAC = real LTV ÷ 3 = ~$10.18
At $1.50 CPC and 3% click-to-paid conversion:
CAC = 1.50 ÷ 0.03 = $50 → 5x over target, unprofitable
Two levers:
(a) raise conversion (paywall work, add a trial)
(b) raise real LTV (push annual plans, move work to cheaper models)
Judging by the $47.94 revenue figure would put your target CAC around $16 — more than 50% above the real ceiling. That gap is the classic way to bleed money slowly while the dashboard looks fine.
Aim for an LTV/CAC ratio of at least 3. Increasing spend below that number just accelerates the loss.
What actually reduced churn
The same usage logs power churn detection:
No session in 7+ days
Weekly usage down 50%+ versus the prior four weeks
Core-feature usage declining while overall sessions hold steady
The third signal proved the most useful. When someone still opens the app but has stopped using the feature they came for, they are usually mid-migration to something else — and that is still early enough to say something.
A save offer in the cancellation flow helps too. Before the final confirmation, offering "three months at 50% off" or "one month free" retains 20–40% of users who intended to leave. I cap it at one offer per user, though; repeat the discount and it stops reading as generous and starts reading as desperate.
Five metrics, checked weekly
Track too many metrics and you will check none of them. These are the five I look at:
Metric
Definition
Threshold
MRR
Monthly recurring revenue
Positive month over month
Gross margin
(Revenue − store fee − AI COGS) ÷ revenue
Investigate below 60%
Churn rate
Paying users cancelling per month
Under 5%
Free-to-paid conversion
Share of free users who subscribe
Around 5% for AI apps
ARPU-to-COGS ratio
Revenue per user ÷ that user's AI cost
4x or better
The middle and last rows are the AI-specific ones. When either starts sliding, the cause is almost always that too many features got routed to the expensive model, or that heavy users have become a larger share of the base. The first calls for moving work back to the cheaper model; the second calls for widening what credits cover.
When you A/B test, change one variable per test. Adjust price and paywall layout together and you will never learn which one moved the number. Get 300–500 users per variant and confirm significance before adopting a winner.
What building this alone taught me
One belief changed over years of shipping apps solo.
I used to treat monetization as something you bolt on afterwards. Finish the features, ship, then add billing. That order felt natural.
With AI apps it is too late by then. The decision about which model powers which feature is the cost structure. Build everything against the top-tier model and then add a subscription, and your only remaining options are raising the price or removing features — both painful after launch.
So now, at the point of designing any feature, I ask once whether the lightweight model would be sufficient. It is an unglamorous habit, and it turned out to be the thing that set my margins.
Rork genuinely does compress implementation time. I have come to read that speed as time returned to design. Being able to build faster meant more hours available to think about what to build — which, working alone, changed more than the velocity itself did.
Where to start
If you are not logging AI calls yet, start there. Write one wrapper function that records user ID, model, token counts, and estimated cost. A week later you will have the number every pricing decision depends on: monthly AI cost per paying user.
The price table and the ad budget can both wait until that number exists.
Thanks for reading — I hope some of this is useful in your own build.
Share
Thank You for Reading
Rork 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.