Fixed monthly infrastructure cost to run the entire stack that powers our £49/mo Lite tier: £13.60. That is not a typo. Variable costs (Claude API, Stripe fees, Twilio per-message) sit on top of the £13.60 and only scale as customers do. Here are the receipts, the design decisions, and the points where this stack is guaranteed to break.

I'm a solo founder. No co-founder, no funding, no developer-hour budget for Kubernetes or AWS bills that scale faster than revenue. The constraint shaped every architectural choice. If you are an indie founder building something similar in 2026, the line items below might save you a thousand pounds and a month of YAML.

The receipts (fixed costs)

Oracle Cloud ARM - 2 vCPU, 24 GB RAM, 200 GB block storage. Hosts everything: FastAPI, cron, send queue, customer state. £0.00
Cloudflare Pages - static site hosting + global CDN for consentleads.uk £0.00
Cloudflare Tunnel - exposes localhost on the Oracle box at demo.consentleads.uk over HTTPS, no port forwarding £0.00
Cloudflare Email Routing + Workers - inbound email forwarding for [email protected] + outbound webhook to FastAPI £0.00
Cloudflare DNS - registrar + DNS for the apex domain £0.00 (annual ~£9)
Resend - transactional email API. Free tier: 3,000/mo, 100/day. Comfortable for the first 10-15 customers. £0.00
Brave Search API - find websites for prospects during sourcing £4.00
Google Places (New) API - vertical-specific business search. Free $200/mo credit covers ~$15/wk of usage. £0.00
Companies House API - UK Limited Company filter by SIC code £0.00
Notion - CRM + Operations wiki (Free Personal plan, unlimited blocks) £0.00
GitHub - source control (Free) £0.00
Tide - UK business bank account (Free tier) £0.00
Cal.eu - scope-call booking page (free, EU instance) £0.00
Domain renewal (consentleads.uk, ~£9/yr -> monthly amortised) £0.75
SSH key, ssl cert, email aliases - all included in Cloudflare suite £0.00
Misc (one-off small purchases: Stripe webhook signing fee, smoke-test domains, etc.) £8.85
Fixed monthly infra (everything always-on) £13.60

Almost the entire fixed cost is "the things that aren't free." Brave Search at £4 covers all the sourcing for our cold outreach pipeline. The £8.85 misc is a handful of pence-level transactional fees that I rounded up to a flat number for honesty. The domain is the only thing where the cost is real and unavoidable.

The variable costs

Variable costs are the ones that scale with usage. They are the right shape: zero customers means zero cost, customers paying us means costs that are a fraction of revenue.

Anthropic API (Claude Sonnet 4.5) - typical Lite customer doing 80-120 DMs/mo at ~700 tokens per reply. Cost per reply ~£0.012. Per Lite customer per month: ~£1.40. ~£1.40 / customer / mo
Stripe - 1.5% + 20p UK card on the £49 Lite charge = £0.94 / mo ~£0.94 / Lite charge
Twilio - per-message SMS for Missed-Call SMS Recovery. ~£0.04 / SMS. Only billed when triggered. Pass-through to client at cost + 20%. ~£0.04 / SMS
Resend - hits paid tier (£16/mo) at ~3,000 emails/mo. Cold outreach + transactional. Currently free. £0 -> £16 at scale

At 10 paying Lite customers, total monthly bill: £13.60 fixed + (10 × £2.34) variable = £37 a month to deliver £490 of MRR. Gross margin sits around 92% before my time. That is the unit economics indie SaaS dreams about.

Architectural decisions, justified

The free-tier stack is only free because of design decisions, not luck. Here are the ones I would not change.

Oracle ARM Always Free instead of AWS/Render/Fly

Oracle gives you 2 ARM-based vCPUs, 24 GB RAM, 200 GB block storage, 10 TB outbound transfer, and a public IPv4, all on the "Always Free" tier. For a small SaaS, this is more than enough. Equivalent AWS spend would be roughly £80-120 a month for a comparable EC2 instance with the same RAM.

The catch: Oracle Always Free instances can be reclaimed if idle. I run a cron job every 30 minutes that pings the demo URL, so the instance counts as "in use" and stays put. So far, 8 months in, zero reclaims.

Cloudflare Tunnel instead of a load balancer

Cloudflare Tunnel exposes a localhost port on the Oracle box to the internet over HTTPS, no NAT punching, no port forwarding, no ALB. Free. You install cloudflared, point it at your FastAPI on localhost:8000, and Cloudflare publishes it at demo.consentleads.uk. Done.

It also gives you Cloudflare's edge for free: DDoS protection, geographic caching, Bot Fight Mode if you turn it on. The only competitor at this price point is ngrok's free tier, which has session limits.

JSONL on disk instead of Postgres

Every piece of state lives in a flat JSONL file on the Oracle box. Customer configs live at demo/customers/{ig_user_id}/config.json. Conversation logs at demo/customers/{ig_user_id}/conversations/{psid}.jsonl. Suppression list at demo/suppressions.jsonl. Cold-email send logs at logs/send_*.log.

Why? Because at 0 - 50 paying customers, JSONL is faster to debug than a database. You can cat the file, you can tail -f it, you can grep across all conversations. You do not need a connection pool, you do not need migrations, you do not need an ORM. The whole “data layer” is open() and json.loads.

This will break at scale. Sometime around 100 active customers I will need SQLite (and SQLite-on-disk is still single-process, no migration drama). Postgres comes in at ~500+ customers if I am still running this solo. Until then, JSONL is the right answer because I can debug it without leaving my terminal.

cron and at instead of a job queue

UK cold-email batches fire at 10:00 and 15:00 UTC via Linux at jobs, scheduled the day before by schedule_30_day.py. Daily sourcing (Google Places) runs at 05:30 UTC via cron. Reply triage runs every 4 hours via cron. Bounce handler runs at 03:00 daily via cron.

I could have set up Celery + Redis. I did not. Cron is 50 years old, in the kernel, never crashes, has zero ops burden. The at daemon handles one-shot future-dated jobs which is exactly what cold-email batching needs.

The whole orchestration layer is about 40 lines of shell. The "queue" is the Linux process scheduler. The "monitoring" is journalctl -u consentleads-demo --no-pager -n 30.

FastAPI + uvicorn + systemd, no Docker

The web app is a single FastAPI process managed by systemd. No Docker, no docker-compose, no Kubernetes. Restart is sudo systemctl restart consentleads-demo. Logs go to a file via StandardOutput=append:/home/ubuntu/freelance/logs/demo.log.

Container orchestration would be the right answer at 5+ environments. I have one. Adding Docker would be 8 hours of work and zero new capability.

Notion for CRM instead of a real database

The CRM is just a Notion database with 800 prospect rows. Notion has a free Personal plan, a usable API, and the front-end I would have to build otherwise. The data sync is a Python script that POSTs to https://api.notion.com/v1/pages.

This is the decision that bothers me most architecturally. Notion's API is rate-limited (3 req/sec) and the data shape is more rigid than I'd like. But the alternative is building a CRM UI, which costs more time than £0 a month is worth. At ~5 paying customers I'll migrate to SQLite + a tiny admin UI.

The general pattern: when a managed service's free tier covers your usage, use it. When the free tier ends and the priced tier is <£20/mo, pay for it. Only build it yourself when both (a) free tiers are gone and (b) priced tiers cost more than the engineering hours you would spend rebuilding it. Most indie SaaS goes broke building things they could have rented for £15.

Where this stack is guaranteed to break

I have written down the next four migrations so I do not pretend I have a permanent solution.

Resend free tier - breaks at ~3,000 emails/mo

Current cold-outreach volume: ~50 sends/day weekdays = ~1,100/mo. Headroom until forced upgrade: about 1,900 emails/mo. At 2 paying Lite customers (cold outreach plus their transactional + welcome emails), I cross into Resend Pro (£16/mo). That triggers our 30-day campaign volume doubling, which is the point of getting paying customers.

JSONL on disk - breaks at ~100 active customers

The bottleneck is list_all() in customer_store.py, which globs every customer directory and reads every config.json. That gets slow when each /dashboard request triggers it. The fix is SQLite, one file, indexed on email + stripe_customer_id + ig_user_id. ~3 days to migrate, no schema headache because the existing JSONL is the schema.

Notion CRM - breaks at ~5 paying customers

Mostly a UX problem. The Notion CRM is brilliant for me; it is hostile to a sub-contractor I might pay to triage replies. The fix is a tiny in-house CRM at /dashboard/admin that lives in the same SQLite as above. ~3 days of work after the JSONL migration.

Oracle Always Free - could change at any time

Oracle Always Free is a marketing program. If Oracle ever decides to pull the tier, we get 60 days notice and need to migrate. Plan B is Hetzner ARM dedicated, £5/mo, no perceptible difference for our workload. Plan C is AWS Lightsail at ~£15/mo. Either way the migration is "rsync the freelance directory, install Python 3.11 + uvicorn, restart". Half a day.

What I'd do differently if I was starting today

Three things, in order of usefulness.

Skip Notion as primary CRM. Build the in-house CRM from day one using SQLite + a 200-line FastAPI admin. It would have been 2 days of work upfront and would have saved me writing 4 different Python scripts to sync data to and from Notion's API. The Notion + custom-sync pattern is fragile and I keep finding edge cases.

Use Cloudflare D1 for early state. D1 is Cloudflare's edge SQLite. It is free up to 5 GB. If I had started with D1 I could have kept the FastAPI on Oracle but pushed customer state to the edge, which would have let me move the dashboard to Cloudflare Workers and drop the Oracle dependency for most requests. I did not because D1 was beta when I started. It is GA now.

Buy a proper Resend domain from day one. I started with the apex domain (consentleads.uk) for both transactional and cold outreach. They have different reputation profiles. Cold outreach burns sender reputation, transactional is fine. They should be on separate subdomains from day one. Now I have to migrate transactional to a clean subdomain before scaling.

If you are building something similar

The whole stack is reproducible in a long weekend if you have a Stripe account and a Cloudflare account.

  1. Oracle Cloud account (free), provision an ARM Always Free VM in London region
  2. SSH in, install Python 3.11, uvicorn, FastAPI, install cloudflared
  3. Point a Cloudflare Tunnel from cloudflared tunnel create at localhost:8000, attach to demo.your-domain.uk
  4. Write the FastAPI routes for whatever your product is
  5. Cloudflare Pages for the marketing site, deploy via wrangler pages deploy
  6. Resend account (free), verify your domain (3 DNS records, 10 minutes)
  7. Stripe account, set up a payment link, point its checkout.session.completed webhook at your FastAPI
  8. Anthropic API key, plug into your FastAPI handler
  9. Cron for daily jobs, at for one-shot scheduled jobs, JSONL for state

Total cost to be in production with a real domain, real HTTPS, real email delivery, real payments: under £15/mo until your first 10 customers. The hardware exists for free because Oracle wants you to upgrade later. Cloudflare's free tier exists because they make money on enterprise. Resend's free tier exists because they want you to grow into the paid tier.

The infrastructure cost is solved. The constraint is finding people who want what you are building.

The hardest part of indie SaaS in 2026 is no longer the infrastructure. It is the distribution.

One thing I am not optimistic about

Cold outreach reputation is the bottleneck I worry about most. Resend has tightened bounce thresholds. Gmail has reduced spam-folder tolerance. Outlook has gotten stricter on SPF/DKIM/DMARC alignment.

You can build a Claude-powered reply system on £13.60/month. You cannot reach the customers who need it for £13.60/month. Distribution costs - paid ads, content, partnerships - are where the real spend goes, and where the real risk lives.

That is the part I am still figuring out. If you have working playbooks for indie SaaS distribution in the UK, my email is below and I will trade you receipts.

I am Sal. Consent Leads is a UK studio shipping Lite (£49/mo, Instagram DM autoresponder) and three larger tiers for service businesses. If you want to argue with any of the architectural decisions above, my email is [email protected]. If you want to compare receipts, even better.