← Case Study Home

The Business
Case
(13 Services → 7, $0/Month)

How do you go from 13 services at $49/month to 7 services at $0/month — and what happens if this thing actually grows?

$0
Monthly infrastructure (V4)
$1.99
Pro tier / month
$0
Ad revenue. Ever.
0
Services running

Part of the ForkIt! Case Study. Back to the case study →

Scroll to explore

The Constraint: "As Free As Possible"

"As free as possible" is not a business model. It is a constraint that forces better architecture, better caching, and better decisions about what to build.

What It Sounds Like

  • Charity. Underpricing. A hobby project that doesn't take money seriously.
  • "You should charge more." "You need a revenue model." "Free doesn't scale."
  • Every advisor, every pitch deck template, every SaaS playbook says the same thing.

What It Actually Is

  • A forcing function. Every feature gets asked: "Does this need an API call?"
  • An architecture driver. Pool caching, client-side filtering, local re-rolls: all exist because of this constraint.
  • A trust signal. No ads, no tracking, no sponsored listings. The user is the user, not the product.
The constraint didn't make the app successful. It made the architecture honest. Every feature that exists earned its place by answering "does this need to cost money?" first.
The Numbers

Where the Money Goes

V3: 13 services, ~$49/month

Google Places API~$49/mo
Vercel (hosting + serverless)Free tier
Vercel KV (Redis)Free tier
Clerk (auth)Free tier
Neon (Postgres)Free tier
RevenueCat (IAP)Free tier
Sentry, GitHub, ImprovMX, ExpoFree tier
Apple + Google + domain~$12/mo amortized
Total~$49/mo + fixed

V4: 7 services, $0/month

Google Places API$0 (within free cap)
Vercel (hosting + serverless)Free tier
Vercel KV (Redis)Free tier
Sentry, GitHub, ImprovMX, ExpoFree tier
Apple + Google + domain~$12/mo amortized
Clerk, Neon, RevenueCatRemoved
Total$0/mo variable

What Changed

V4 asked: "Does this service serve sustainability or conversion?" At fewer than 100 users, the answer for auth, database, and purchase middleware was: neither. Clerk was removed (no accounts needed). Neon was removed (local storage + export/import). RevenueCat was removed (react-native-iap talks to stores directly). The API cost dropped from $49/month to $0 by switching free users from Enterprise field masks to Pro field masks (same data the user sees, different billing tier).

April 2026 Actuals: Prediction Becomes Receipt

V4 Phase 1 shipped in late March with a tier-split prediction: route free users to Pro field-mask billing, gate filters that require Enterprise fields behind a paid tier, and cut billable Enterprise calls by ~95%. The first full month post-V4 was April. The Google billing report makes the verdict simple.

Q1 2026 vs April 2026 (Google Billing CSV)
Q1 2026 (pre-V4) Nearby Search Enterprise7,374 calls
Q1 2026 net (after trial credit)$176.75
April 2026 Nearby Search Enterprise132 calls
April 2026 Nearby Search Pro623 calls
April 2026 net$0.00

Free users now route to the cheaper Pro field mask. April fell entirely within Google's free monthly cap. The break-even target dropped from ~42 subscribers to effectively zero. Every paid subscriber is pure margin after API cost.

The Expensive Part

The API Problem

Google Places is the only real cost. And it cost more than expected.

The Pricing Discovery

The LLM stated that Google Maps Platform included a $200/month free credit. Architecture decisions, cost projections, and the free tier design were all built on this assumption. The credit had been eliminated over a year before the project started. The LLM's training data was stale. Every cost calculation based on that number was wrong.

On top of that, Nearby Search and Text Search hit Enterprise SKU pricing (higher per-call costs than the Basic endpoints used for simple geocoding). The app was hitting the most expensive tier of an API with no credit to offset it.

Lesson: never trust LLM pricing knowledge. Verify vendor pricing pages directly before making cost-driven architecture decisions.

The Fix: Pool Caching

The single biggest cost optimization in the entire app. One architectural decision that turns dozens of potential API calls into one.

🔅 User Taps "Fork It"
Cache Check Pool exists? Filters same?
🔒 Google Places API $0.032 per call
🍴 Local Pool 20+ restaurants cached
Random Pick $0.00 per re-roll

First Tap: API Call

User taps "Fork It" for the first time. No cache exists yet. The app calls Google Places API and fetches a full pool of 20+ restaurants matching the current filters.

Cost: ~$0.032

Second Tap: Free

User doesn't like the suggestion. Taps again. The app picks a different restaurant from the same cached pool. No API call. No cost.

Cost: $0.00

Third, Fourth, Fifth Tap: Still Free

Every re-roll picks from the local pool. A user could tap 50 times and it's still one API call. The pool doesn't expire for 8 hours.

Cost of 50 re-rolls: $0.032 total

Filter Change: New Call

User changes a filter (different cuisine, different radius, different price range). The cached pool no longer matches. A new API call fetches a fresh pool.

This is what counts as a "search" against the free tier limit.

The Math

Without pool caching, a user who taps 10 times costs $0.32. With it, they cost $0.032. That is a 10x cost reduction from one architectural decision.

A casual user who searches once and re-rolls a few times costs the same as a single API call. The caching makes the free tier viable.

Beyond Pool Caching

Multiple layers of optimization reduce per-search cost further.

Multi-Layer Caching

  • Server-side Redis cache (8-hour TTL). Users in the same area share one API fetch from lunch through dinner
  • Mode-aware cache grid: walk mode and short drives (<5km) use tight ~1.1km buckets for accuracy; longer drives use ~11km buckets for cache sharing
  • Autocomplete suggestions cached server-side, reducing redundant keyword lookups
  • Fixed 2-call search: every no-keyword fork makes exactly 2 API calls (distance + popularity)

Cache TTL evolved from 1hr → 3hr → 8hr as usage patterns showed restaurant data doesn't change mid-meal-decision.

Client-Side Intelligence

  • Field masks on every request (only fetch name, address, rating, price; skip photos and reviews)
  • Details endpoint removed from the main flow (pool data is sufficient for the pick)
  • Chain detection, exclude filter, and all re-rolls operate on local data
  • Client pool cache (8-hour TTL); repeat forks within a day never hit the backend
The Model

The Revenue Model

Pro exists to offset API costs, not as a revenue model. The goal is sustainability, not growth-at-all-costs.

How the Revenue Model Evolved

v2 launched with two tiers. The margin problem became obvious immediately.

v2: Two Tiers (The Margin Problem)

Free users got 20 searches and cloud sync. Pro ($1.99) got unlimited everything. The problem: every user (including free users) hit Neon, Clerk, and the backend for sync. A power Pro user who searched 50 times a month cost ~$1.60 to serve and paid $1.69 net. That is a $0.09 margin on the most engaged users.

The users who cost the most paid the same as the users who cost the least.

v3: Three Tiers (March 2026)

The fix: align cost with revenue. Cloud sync (the most expensive feature to serve) moved behind Pro+. Free tier limits tightened to reduce API spend per non-paying user.

Free

  • 10 searches/month
  • 1 group session/month
  • Unlimited re-rolls
  • Local data only

Pro ($1.99/mo)

  • 20 searches/month
  • 3 group sessions/month
  • Unlimited re-rolls
  • Local data only

Pro+ ($4.99/mo)

  • Unlimited searches
  • Unlimited group sessions
  • Export/import data backup

A "search" = a new API fetch. Re-rolls from the cached pool are free and unlimited. Managed through react-native-iap, communicating directly with Apple and Google stores. No third-party purchase server.

What Will Never Exist

  • No advertising. Not banner ads. Not sponsored listings. Not "promoted" restaurants. Not ever.
  • No tracking. No analytics that follow users across apps. No selling user data. No ad networks.
  • No pay-to-rank. Restaurant owners cannot buy placement. The randomization is honest.

This is a hard rule, not a preference. It is documented in the project guide, enforced in code reviews, and has been tested by real offers from restaurant owners.

Code Protection

The codebase uses a Business Source License (BSL). The code is visible on GitHub for portfolio and transparency purposes, but commercial use requires a license. This protects the work without hiding it.

Usage Enforcement at Scale

Free tier limits are tracked per-device via AsyncStorage with monthly resets, not per-account (accounts were removed in V4). A determined user could bypass them by clearing app data or reinstalling. At ~100 users and $1.99/month, the incentive to game it is near zero. But the architecture doesn't scale.

Server-side usage tracking (keyed by device ID or fingerprint) is the obvious fix. The question is when the risk justifies the complexity. Right now, the answer is: not yet. The cost of a handful of users gaming the free tier is less than the cost of building and maintaining server-side enforcement.

The Projections

What Breaks at Scale

Every free tier has a ceiling. Here is where each service hits its limit, and what it costs to cross.

Unit Economics

Cost per casual user (5 searches/month)~$0.05
Cost per active user (20 searches/month)~$0.20
Cost per power user (50+ searches/month)~$0.50
Revenue per Pro subscriber (after store cut)~$1.69
Breakeven per Pro user~3 searches/month

Revenue per subscriber assumes Apple/Google's 15% small business cut (under $1M annual revenue): $1.99 x 0.85 = $1.69. Multi-layer caching (8-hour server Redis, 8-hour client pool, mode-aware location grid) drives per-user costs down ~3x compared to simple pool caching alone. Most searches in populated areas hit cache, making even power users profitable.

Why Not Switch Providers?

When Google API costs became the dominant variable, the obvious question was: can we use something cheaper? The answer required evaluating every alternative against the features users actually depend on.

Foursquare: Has ratings, but they're algorithmic (based on check-in traffic), not user reviews. Many restaurants (especially outside major metros) have no rating at all. The fields ForkIt needs (rating, price, hours) are all "Premium" tier: $18.75/1,000 calls with zero free tier. Their V3 API is also being deprecated May 2026. OSM/Overpass: Free and unlimited, but no ratings, no price level, no real-time "open now." HERE: Generous free tier (250K calls/month) but also lacks ratings. Apple MapKit: Free, but no ratings, and would require managing separate iOS/Android search paths. The Group Fork feature merges filters server-side, making a platform split impractical.

The conclusion: when a user sets "4 stars and up," that filter has to work. Only Google provides reliable restaurant ratings at scale. The cost strategy is "fewer Google calls," not "different provider." Every cache optimization exists because of this constraint.

Vendor Dependency

7 services. Most on free tiers. Google already killed its $200/month API credit without warning (March 2025). The remaining dependencies: Vercel, Google Places API, Sentry, Redis (Vercel KV). Any of them could change pricing or terms.

How does a solo dev build resilience against platform risk when every alternative means rebuilding? The answer, right now, is: you don't. You monitor, you keep alternatives in mind, and you accept that the free tier is rented ground. The 31-review suite includes Review 25 (Dependency Health) for exactly this reason, but a review can flag the risk. It can't eliminate it.

Update (March 2026): A full evaluation of Foursquare, OSM, HERE, and Apple MapKit confirmed that Google lock-in for restaurant data is real; no alternative provides the ratings and price data that ForkIt's filters require. The mitigation isn't to switch providers but to minimize call volume through aggressive, mode-aware caching. The research is documented in the project's issue tracker for future revisiting as the market evolves.

The Real Math

The Path to Break Even

The goal is not profit. The goal is: this app should not cost money out of pocket to keep running. Break even is the floor. Everything above that is a bonus.

The Tier Economics

Each tier is designed so the features that cost the most to serve are behind the tier that charges the most. Here is what each tier costs to operate.

Free

  • 10 searches/month
  • 1 group session/month
  • Unlimited re-rolls
  • Random pick only (no filters)
  • Favorites, history, spots (local only)

Cost to serve: ~$0.32/mo

No database load

Pro ($1.99/mo)

  • 20 searches/month
  • 5 group sessions/month
  • Unlimited re-rolls
  • Full filters
  • Favorites, history, spots (local only)

Cost to serve: ~$0.96/mo

Net: $1.69. Margin: $0.73

Pro+ ($4.99/mo)

  • Unlimited searches
  • Unlimited group sessions
  • Export/import data backup
  • All filters + richer data
  • Everything in Pro

Cost to serve: ~$2.00/mo

Net: $4.24. Margin: $2.24

The Simpler Truth

Forget conversion rate projections and user-count modeling. The actual question: what does it cost to keep this app alive, and can a handful of people cover it?

Google Places API (~100 users)$0/mo (within 5K Pro free cap; costs start at ~1,250 active users)
Apple Developer Program (amortized)~$8/mo
Domain~$1/mo
Everything elseFree tier
Total to keep it running~$9/mo

That is 6 Pro subscribers. Or 4 Pro+ subscribers. That is the real break-even target.

Not 200 users with optimistic conversion rates. A handful of people who use the app enough to pay for it.

Will People Pay?

Probably not many. The problem ("where should we eat?") is real but feels trivial. People don't pay to solve problems they think they can push through. Similar apps have struggled; UrbanSpoon got acquired and dissolved. Most "random restaurant" apps have under 1,000 downloads.

The differentiator (no ads, honest randomization) is appreciated, but principles are not features people open their wallets for.

Where the money is, if anywhere: Group Fork. It has a "right now" moment (group dinner, everyone arguing). People pay at the point of pain, not in advance. The tiered model puts that behind Pro+, which is where it should be.

The Honest Sunk Costs

Infrastructure is not the real expense. This project also consumed:

Claude subscription (AI development partner)$100/mo ongoing
MacBook (development hardware)One-time purchase
Apple Developer Program$99/year
Google Play Developer$25 one-time
EAS builds (local via --local flag)$0 (cloud builds eliminated)
Development time (nights, weekends, breaks)75 days and counting

The Claude subscription alone costs 7x what the infrastructure does. But Claude is not a ForkIt cost; it is a personal development tool used across all projects. ForkIt is one beneficiary of a tool that would exist anyway.

The sunk costs will never be recouped by a $1.99 app with ~100 users. That is fine. This is a portfolio piece that demonstrates capability. The only financial requirement: the app should not cost money out of pocket to keep running.

Break even is the floor. Everything above that is a bonus.

The Deep-Dive

The Pricing Deep-Dive

Three months. Three pricing models. Each one taught something the previous one couldn't.

Where We've Been

v1-v2: All Free, All Enterprise (January-March 2026)

Every user got the same API calls. Every search hit Google's Enterprise tier because the field mask included rating, priceLevel, and currentOpeningHours. Free and paid users were identical from Google's billing perspective.

The assumption: a $200/month Google Maps credit would cover it. That credit had been eliminated a year before the project started. The LLM's training data was stale. By the time real billing data arrived, the architecture was locked in.

Result: ~$43/month API cost (Feb 2026 actual: $42.77) for ~100 users, 100% of it from Nearby Search Enterprise. Everything else (Place Details, Text Search, Autocomplete) fit within free caps. V4 eliminated this cost entirely.

Where We Were

v3: Three Tiers to $4.99 (March 2026 — superseded by V4)

Free (10 searches/month), Pro ($1.99, 20 searches), Pro+ ($4.99, unlimited + cloud sync). The three-tier model aligned cost with revenue: cloud sync (the most expensive feature) moved behind Pro+.

But an uncomfortable truth emerged: who pays $5/month for a food picker app? The problem ForkIt solves feels trivial. Competitors are free. The value proposition for Pro+ (cloud sync + unlimited) is real but not compelling enough to justify 2.5x the Pro price.

And the deeper problem: all three tiers still hit the same Enterprise API tier. Free users cost the same to serve as Pro+ users. The pricing tiers existed for revenue, but the architecture didn't match.

What the Deep-Dive Revealed

A full audit of Google's field-to-tier mapping, actual billing data, and unit economics exposed the real cost structure.

The Discovery: Field Masks Control Billing

Google doesn't bill by endpoint. It bills by the highest-tier field in your request. Four fields lock Nearby Search into Enterprise billing ($35/1K, 1,000 free/month): rating, priceLevel, currentOpeningHours, userRatingCount.

Remove those fields, and the same call bills at Pro ($32/1K, 5,000 free/month). Current volume of ~2,400 calls/month fits entirely within the Pro free cap.

One field mask change: $49/month to $0/month.

The Insight: Align API Tiers with Pricing Tiers

The Enterprise fields that cost more to request are the same fields that power the premium features (rating filter, price filter, open-now filter). Free users don't need those fields if they don't have access to those filters.

This creates a natural alignment: features that cost more to serve are gated behind tiers that generate revenue. Free users get the core experience (random pick with name and location) at zero API cost. Paid users get filters and richer data, paid for by their subscription.

API Tier Alignment
Free user searchPro fields (within 5,000 free cap) = $0/month
Pro/Pro+ user searchEnterprise fields = ~$0.97/user/month
Detail tap (all users)Enterprise (within 1,000 free cap) = $0/month
Autocomplete (all users)Session-based = $0/month

The 15% Discovery

Apple's Small Business Program reduces the App Store commission from 30% to 15% for developers under $1M in annual revenue. Google Play's 15% on the first $1M is automatic. This nearly doubles the per-user margin.

At 15% cut, a Pro subscriber at $1.99 keeps $1.69 (not $1.39). A Pro+ subscriber at $2.99 keeps $2.54 (not $2.09). The difference between "barely profitable" and "solid margin" was a form submission.

Lesson: check your store commission rate before building a revenue model. The default assumption of 30% may be leaving 15% on the table.

Where We Are Now

V4: Three Tiers to $2.99 (Current — April 2026)

Pro+ lowered from $4.99 to $2.99. The $1 jump from Pro ($1.99) to Pro+ ($2.99) is psychologically easy. "Just a dollar more for unlimited." Cloud sync removed; replaced with export/import. Clerk, Neon, and RevenueCat all removed.

Free

  • 10 searches/month
  • 1 group session/month
  • Random pick (no filters)
  • Full details on tap

API: Pro tier = $0

Pro ($1.99/mo)

  • 20 searches/month
  • 3 group sessions/month
  • Rating, price, open-now filters
  • Richer pick card data

API: Enterprise = ~$0.97/user

Pro+ ($2.99/mo)

  • Unlimited everything
  • Export/import data backup
  • All filters

API: Enterprise = ~$1.61/user

The Unit Economics (at 15% Store Cut)

Free userAPI: $0.00 | Revenue: $0.00 | Net: $0.00
Pro user ($1.99)API: $0.97 | Revenue: $1.69 | Net: +$0.72
Pro+ user ($2.99)API: $1.61 | Revenue: $2.54 | Net: +$0.93

Every tier is net positive. Free users cost nothing. Paid users more than cover themselves. The break-even target at current scale is effectively zero subscribers.

The Honest Ceiling

Even in the most optimistic viral scenario (100K installs, App Store feature), ForkIt nets ~$500-1,000/month by month 12 at $1.99/$2.99 pricing. This is a niche utility app, not a social platform. ~80% of installs churn in week 1. ~3-4% of active users convert to paid. Paid subscribers cancel at ~8-10%/month.

This is not "quit your job" money. The ceiling is a meaningful side income, not a startup outcome. The things that move the needle more than virality: retention past week 1, conversion rate improvements, and reducing subscriber churn.

The architecture ensures the app doesn't lose money at any scale. That's the win. Everything above $0 net is a bonus.

Subscription billing has its own engineering pitfalls (group level inversion on iOS, replacement params on Android, paywall tier-awareness, sales-report lag) that aren't pricing decisions; they're platform contract decisions. They live on the Platform Engineering page.

The Principle

The Monetization Test

The principle wasn't born in a strategy session. It was crystallized by two conversations that arrived uninvited.

The Restaurant Owners

Two restaurant owners, separately, asked the same question: "Can we pay to show up more often?"

The answer was immediate and easy. No. The app picks randomly. If you can buy placement, the randomization is dishonest, and the entire value proposition collapses. Users trust the pick because nothing influences it except their own filters.

The moment someone can buy a better result, the app becomes an ad platform. That is a different product.

The Yelp 2.0 Prediction

A friend, watching the app grow, predicted: "You're going to end up building Yelp 2.0. Reviews, business pages, sponsored content. That's where the money is."

He was describing the standard playbook. Build the audience, monetize the attention. Every food app eventually becomes an advertising platform for restaurants.

That prediction became the clearest articulation of what not to build. The constraint isn't "we can't afford ads." It is "ads would destroy the thing that makes this useful."

The friend who predicted Yelp 2.0 wasn't wrong about the industry. He was wrong about this project. "As free as possible" is not naive idealism. It is the only business model where the product stays honest.

The Honest Business Case

This app will probably not make money. The problem it solves feels trivial. The market is small. Similar apps have failed.

But it costs ~$9/month to keep alive. It takes $0 from advertisers. And it demonstrates that a solo builder with no dev background can ship a real product, operate 7 services, and make deliberate cost decisions at every layer of the stack.

The business case is not the revenue. The business case is the capability.

Part of that capability: an explicit choice about what to open and what to protect. The client code is public at forkit-open under PolyForm Noncommercial, so readers can study a shipped indie React Native codebase. The backend — API key, caching strategy, curated chain list, paywall enforcement — stays closed. Open enough to be a case study; closed enough to keep future options available.

Break even is the floor. The portfolio is the point.