Costs & Usage — Full Analysis
Status: Active Owner: @bilal @danny Last Updated: 2026-02-24
TL;DR
| Scale | Properties | Infra + Variable | Stripe Fees | Grand Total | Per-Property |
|---|---|---|---|---|---|
| Now (dev) | 0-5 | ~$32 | — | ~$32 | N/A |
| Early users | 50 | ~$83 | ~$19 | ~$102 | ~$2.04 |
| Growth | 500 | ~$418 | ~$190 | ~$608 | ~$1.22 |
| Scale | 1,000 | ~$792 | ~$380 | ~$1,172 | ~$1.17 |
| Target | 3,000 | ~$2,275 | ~$1,140 | ~$3,415 | ~$1.14 |
Notes: ZTNA (Cloudflare Access) removed when app goes public — saves $420/mo at 3K. Voice is Premium/Partner tier only. Twilio is the dominant cost (65% at scale).
Optimised target (SMS→WhatsApp shift + direct Meta API): ~0.56/property**. At target scale, minimum viable charge is ~$1.50-2/property/mo to break even with margin.
Pricing Validation Log
All prices verified against live pricing pages on 2026-02-23. Prices change frequently — revalidate quarterly.
| Service | Doc Price | Verified Price | Source | Status |
|---|---|---|---|---|
| Cloudflare Workers Paid | $5/mo | $5/mo + 10M req + 30M CPU ms | developers.cloudflare.com/workers/platform/pricing | Correct |
| Supabase Pro | $25/mo | $25/mo (org-based billing) | supabase.com/pricing | Correct |
| Supabase Storage overage | $0.021/GB | $0.021/GB | supabase.com/docs/guides/platform/billing-on-supabase | Correct |
| Supabase Egress | $0.09/GB | $0.09/GB after 250 GB | supabase.com/docs/guides/platform/billing-on-supabase | Correct |
| Supabase DB overage | $0.125/GB | $0.125/GB after 8 GB disk | supabase.com/docs/guides/platform/billing-on-supabase | Correct |
| Supabase Auth MAU | $3.25/1K | 3.25/1K) | supabase.com/docs/guides/platform/billing-on-supabase | Correct |
| Twilio SMS UK outbound | $0.046 | $0.0524 | twilio.com/en-us/sms/pricing/gb | UPDATED (+14%) |
| Twilio UK phone number | ~$1/mo | $1.15/mo | twilio.com/en-us/sms/pricing/gb | UPDATED |
| Claude Sonnet 4.6 | 15 per MTok | 15 per MTok (≤200K ctx) | claude.com/pricing | Correct |
| Claude Haiku 4.5 | — | 5 per MTok | claude.com/pricing | New model |
| OpenAI embeddings | $0.02/MTok | $0.02/MTok (text-embedding-3-small) | openai.com/api/pricing | Correct |
| Stripe UK standard | 1.5% + 20p | 1.5% + 20p | stripe.com/gb/pricing | Correct |
| Stripe Billing | +0.5% | 0.7% or from £450/mo annual | stripe.com/gb/pricing | UPDATED — pay-as-you-go is 0.7% not 0.5% |
| Resend Pro | — | $20/mo (50K emails) | resend.com/pricing | New (replacing SendGrid) |
| Retell AI | ~$0.10/min | $0.07+/min (infra+voice+LLM+telephony) | retellai.com/pricing | UPDATED — component pricing changed |
1. Complete Service Inventory
Every service Envo uses or will use, with nothing left out.
| # | Service | Component Used | Pricing Model | Current Tier |
|---|---|---|---|---|
| 1 | Cloudflare Workers | Dashboard hosting (Next.js via @opennextjs/cloudflare) | $5/mo base + per-request overage | Paid |
| 2 | Cloudflare Pages | brain.ehq.tech (Quartz) + ehq.tech marketing site (Astro) | Included in Workers Paid | Paid |
| 3 | Cloudflare Hyperdrive | Connection pooling to Supabase Postgres | Included in Workers Paid | Paid |
| 4 | Cloudflare DNS | ehq.tech zone, proxied records | Included | Free |
| 5 | Cloudflare Access (ZTNA) | Email OTP auth gate for app + brain — will be removed when app goes public | Free ≤50 users | Free (temporary) |
| 6 | Supabase — Database | PostgreSQL 16 + pgvector (1536-dim embeddings) | $25/mo Pro, 8 GB disk included | Free* |
| 7 | Supabase — Auth | JWT auth, SSR, user sync triggers | 100K MAUs included on Pro | Free* |
| 8 | Supabase — Storage | 3 buckets: issue-attachments (10 MB limit), property-documents (20 MB limit), chat-uploads (5 MB limit) | 100 GB included on Pro | Free* |
| 9 | Not currently used — GraphQL subscriptions via Yoga, not Supabase Realtime | 5M messages included (unused) | Free* (included) | |
| 10 | Supabase — Vault | Encrypted credential storage (pgsodium) for BYOAK | Included on Pro | Free* |
| 11 | Anthropic Claude | Primary LLM — Sonnet 4.6 for generation + tool use | 15/M output tokens | Pay-as-you-go |
| 12 | OpenAI | Embeddings (text-embedding-3-small) + fallback LLM | $0.02/M tokens (embeddings) | Pay-as-you-go |
| 13 | Twilio — SMS | UK outbound notifications to landlords, tenants, vendors | 0.0075/msg inbound | Pay-as-you-go |
| 14 | Twilio — WhatsApp | Tenant conversations (primary V1 channel) | $0.005/msg + Meta template fees | Pay-as-you-go |
| 15 | Twilio — Phone Numbers | UK numbers for SMS/WhatsApp | $1.15/mo per number | Pay-as-you-go |
| 16 | Resend | Email notifications (landlord summaries, vendor assignments) | Free (3K/mo, 100/day) → Pro $20/mo (50K) | Free |
| 17 | VAPI / Retell | Voice AI agent for tenant calls | ~$0.09-0.17/min all-in | Pay-as-you-go |
| 18 | PostHog Cloud EU | Website analytics (cookieless mode, Frankfurt) | Free (1M events/mo) → Growth $0/mo base | Free |
| 19 | ehq.tech domain | Domain registration | ~$10/yr | Annual |
| 19 | Terraform Cloud | IaC state for Cloudflare infra (~15 resources) | Legacy free until Mar 2026 | Free (legacy) |
| 20 | GitHub | Repo + GitHub Actions CI/CD | Free tier | Free |
| 21 | ProtonMail | Team email hosting | Existing Duo plan | Existing |
| 22 | Stripe (planned) | Subscription billing, payments | 1.5% + 20p per transaction | Not yet |
* Supabase is currently on the Free tier for development. Will upgrade to Pro ($25/mo) before any real users. All costings below assume Pro.
2. Fixed Infrastructure (Monthly)
Services that cost the same regardless of property count.
| Service | What It Does | Current Cost | Notes |
|---|---|---|---|
| Cloudflare Workers Paid | Dashboard + Pages + Hyperdrive + DNS | $5/mo | 10M requests + 30M CPU ms included. Static assets free and unlimited. |
| Supabase Pro | DB + Auth + Storage + Vault | $25/mo | See Supabase deep-dive below (Realtime not used). Currently on Free for dev. |
| ehq.tech domain | DNS | **~0.83/mo) | .tech domain renewal |
| Resend | Email sending | 20/mo (growth) | Free tier: 3K emails/mo, 100/day limit. Pro at $20/mo for 50K emails/mo. |
| Terraform Cloud | IaC state | $0 | Legacy free tier until Mar 2026 |
| Cloudflare Access | ZTNA auth gate | $0 | Free for ≤50 users |
| GitHub | Repo + CI/CD | $0 | Free tier |
| ProtonMail | Email hosting | $0 | Existing Duo plan |
**Current fixed total (dev): ~31. Currently ~$6 on Free.)
**Fixed total (growth): ~20/mo)
Supabase Pro Deep-Dive
Everything included in the $25/mo Pro plan and what triggers overages:
| Component | Included (Pro) | Overage Rate | When You Hit It |
|---|---|---|---|
| Database (Postgres + pgvector) | 8 GB disk per project | $0.125/GB | ~500-1,000 properties (est. 2-3 KB/property for core data, but vectors add up — 1536-dim × 4 bytes × chunks) |
| Auth (MAUs) | 100,000 | $0.00325/MAU | Unlikely — dashboard users only (tenants don’t have auth accounts) |
| File Storage | 100 GB | $0.021/GB | ~5,000+ properties at 5 docs × 2 MB avg = 50 GB for 5K props |
| Bandwidth / Egress | 250 GB | $0.09/GB | High API traffic or large file downloads |
| Realtime Messages | 5,000,000 | $2.50/million | Not used — real-time via GraphQL subscriptions (Yoga), not Supabase Realtime |
| Edge Function Invocations | 2,000,000 | $2/million | Not currently using edge functions |
| Compute | Included with project | Add-on pricing | See compute add-on section below |
Key insight: Auth MAUs will stay well under 100K because tenants don’t log in via Supabase Auth — they interact via WhatsApp/Voice/Chat. Only dashboard users (landlords, staff) use Supabase Auth. Even at 3,000 properties you’d have maybe 200-500 dashboard users.
Vector storage estimate: At 3,000 properties × 5 docs × 10 chunks × 1536 dimensions × 4 bytes = ~880 MB just for vectors. Add metadata and you’re at ~1-2 GB for vector data alone. Total DB at 3K properties (including conversations, messages, events): est. 15-25 GB.
Supabase Compute Add-Ons
Supabase compute is now priced as explicit add-ons per project (not a tiered upgrade with credits):
| Instance | vCPUs | RAM | Approx. Cost/mo | When to use |
|---|---|---|---|---|
| Micro | 2 | 1 GB | Included (Pro) | Dev / early users |
| Small | 2 | 2 GB | ~$25/mo | ~100-300 properties |
| Medium | 2 | 4 GB | ~$50/mo | ~300-700 properties |
| Large | 2 | 8 GB | ~$100/mo | ~700-1,500 properties |
| XL | 4 | 16 GB | ~$200/mo | ~1,500-3,000 properties |
| 2XL | 8 | 32 GB | ~$400/mo | 3,000+ properties |
Note: Exact compute pricing should be verified in the Supabase dashboard as it changes. The above are estimates based on current published rates.
Fixed Cost Scaling Triggers
| Trigger | When | Cost Impact |
|---|---|---|
| Supabase Free → Pro upgrade | Before any real users | +$25/mo |
| Supabase compute upgrade (Small) | ~100-300 properties | +$25/mo |
| Supabase compute upgrade (Medium) | ~300-700 properties | +$50/mo (replacing Small) |
| Supabase DB > 8 GB | ~500-1,000 properties | +$0.125/GB overage |
| Supabase storage > 100 GB | Heavy document uploads | +$0.021/GB overage |
| Supabase bandwidth > 250 GB | High API traffic | +$0.09/GB overage |
| Terraform Cloud free tier ends | Mar 2026 | ~1.50/mo) |
| Resend Free → Pro upgrade | >3K emails/mo OR >100/day | +$20/mo |
| Resend Pro → Scale upgrade | >50K emails/mo | +20 → $90) |
| Workers > 10M requests/mo | Very high scale | +$0.30 per million requests |
| Supabase Team plan (for SAML) | White-label Partner tier | Jump from 599/mo |
3. Variable Costs — Per-Conversation AI
The biggest variable cost driver. Each tenant conversation involves LLM calls for intent classification, tool-use orchestration, and RAG generation.
Cost Per Conversation Breakdown
Based on ADR-017 and RAG Pipeline docs, a typical issue-reporting conversation has ~4-6 turns.
| Component | Cost Per Turn | Cost Per Conversation (5 turns) |
|---|---|---|
| Claude Sonnet 4.6 (generation + tool use) | ~$0.003-0.01 | ~$0.015-0.05 |
| Claude Haiku 4.5 (reranking, future) | ~$0.001-0.003 | ~$0.005-0.015 |
| OpenAI embeddings (query) | ~$0.0001 | ~$0.0005 |
| Total AI per conversation | ~$0.02-0.06 |
Cost Per Q&A Query (no issue created)
Simpler — typically 1-2 turns.
| Component | Cost |
|---|---|
| Claude generation | ~$0.01-0.03 |
| OpenAI embedding query | ~$0.0001 |
| Total per Q&A | ~$0.01-0.03 |
Document Ingestion (One-Time Per Document)
| Component | Cost Per Document |
|---|---|
| Text extraction | $0 (local) |
| Chunking + embedding (avg 10 chunks) | ~$0.0002 |
| Total per document | ~$0.001 (negligible) |
4. Variable Costs — Notifications & Messaging
Clarification: What Uses What
| Channel | Used For | Provider |
|---|---|---|
| Tenant conversations (primary inbound channel) | Twilio as BSP (see migration path below) | |
| SMS | Outbound notifications to landlords, tenants, vendors | Twilio |
| Non-urgent notifications, summaries, vendor assignments | Resend |
Important: Twilio is the BSP (Business Solution Provider) for WhatsApp, not the messaging platform itself. Meta’s WhatsApp Business API is the underlying service — Twilio just provides the API wrapper and phone number hosting.
SMS Notification Cost Per Issue
| Event | Channel | Recipients | Cost Per Message | Subtotal |
|---|---|---|---|---|
| Issue created | SMS to landlord | 1 | $0.0524 | $0.0524 |
| Issue created | Email to landlord | 1 | ~$0.0004 | ~$0.0004 |
| Issue created | SMS confirmation to tenant | 1 | $0.0524 | $0.0524 |
| Vendor assigned | SMS + Email to vendor | 1 | 0.0004 | $0.053 |
| Vendor accepts | SMS to landlord + tenant | 2 | $0.0524 × 2 | $0.1048 |
| Issue completed | Email to landlord + tenant | 2 | ~$0.0004 × 2 | ~$0.001 |
| Total per issue lifecycle | ~$0.26 |
WhatsApp Costs (Tenant Conversations)
| Item | Via Twilio BSP | Direct Meta Business API |
|---|---|---|
| Twilio per-message markup | $0.005/msg | N/A |
| Meta utility template (UK) | ~$0.02/template | ~$0.02/template |
| Meta service conversations | First 1,000/mo free | First 1,000/mo free |
| Avg conversation (8 msgs) | ~$0.04-0.20 | ~$0.00-0.16 |
WhatsApp Migration Path: Twilio → Direct Meta Business API
Twilio adds a $0.005/msg markup on top of Meta’s own fees. At scale this adds up:
| Scale | WhatsApp msgs/mo | Twilio markup saved | Annual saving |
|---|---|---|---|
| 500 props | 6,000 | $30/mo | $360/yr |
| 1,000 props | 12,000 | $60/mo | $720/yr |
| 3,000 props | 36,000 | $180/mo | $2,160/yr |
Migration options:
-
Direct Meta WhatsApp Business API — Use Meta’s Cloud API directly. Eliminates Twilio markup entirely. Requires webhook hosting (already have Cloudflare Workers) and number porting. Meta conversation pricing still applies.
-
BYOAK for WhatsApp (ADR-014) — Partner-tier orgs bring their own Meta Business account or Twilio credentials. Shifts entire WhatsApp cost to customer.
-
Alternative BSPs — 360dialog, MessageBird/Bird, Infobip offer lower per-message markups than Twilio (0.005).
Recommendation: Start with Twilio (fastest to ship), plan migration to direct Meta Cloud API by ~500 properties. The $0.005/msg markup is acceptable at low scale but worth eliminating at 1K+.
SMS: Keep or Replace?
SMS is used only for outbound notifications (not conversations). Options:
| Option | Cost/msg | Pros | Cons |
|---|---|---|---|
| Twilio SMS (current) | $0.0524 | Already integrated, reliable | Most expensive |
| Shift to WhatsApp for tenant notifications | ~$0.005-0.02 | 2-10× cheaper than SMS | Requires tenant opt-in, not all tenants on WhatsApp |
| Email-first for non-urgent | ~$0.0004 | Cheapest | Slower, may be missed |
| Push notifications (future mobile app) | ~$0 | Free | Requires app adoption |
Recommendation: Default to WhatsApp for tenant notifications where possible (they’re already on the channel), SMS only as fallback for tenants without WhatsApp, email for non-urgent/digest. This alone could cut notification costs by 50-70%.
Email Provider: Resend (Replacing SendGrid)
We have not yet committed to an email provider. After evaluation:
| Provider | Free Tier | Paid Tier | Pros | Cons |
|---|---|---|---|---|
| Resend (recommended) | 3K emails/mo, 100/day | Pro: $20/mo for 50K | Modern DX, React Email, good free tier, better webhook support | Newer, smaller company |
| SendGrid | 60-day free trial only | Essentials: $19.95/mo for 50K | Established, Twilio ecosystem | Free trial expires, worse DX |
| Postmark | 100 emails/mo free | $15/mo for 10K | Best deliverability reputation | Expensive at scale |
| Amazon SES | 3K/mo free (from EC2) | $0.10/1K emails | Cheapest at scale | Setup complexity, no dashboard |
Decision: Resend — Free tier covers dev, Pro ($20/mo) is competitive, and React Email integration aligns with our React/Next.js stack. The @sendgrid/mail package currently in package.json should be replaced with Resend’s SDK when email integration is implemented.
At 3,000 properties (est. ~6K emails/mo), Resend’s Free tier might actually suffice if daily limits aren’t hit. Pro at $20/mo gives comfortable headroom.
5. Variable Costs — Voice AI (VAPI / Retell)
Voice is the most expensive per-interaction channel.
Retell All-In Cost (Verified 2026-02-23)
Retell now uses component-based pricing:
| Component | Per Minute | Notes |
|---|---|---|
| Retell Voice Infra | $0.055 | Platform + orchestration |
| TTS (Cartesia/Minimax/ElevenLabs) | $0.015 | All voice providers same price |
| LLM (Claude 3.5 Haiku) | $0.020 | Cheapest Claude option |
| LLM (Claude 3.7 Sonnet) | $0.060 | Higher quality |
| Telephony (Retell Twilio, UK) | $0.10 | UK international rate |
| Telephony (Custom/SIP) | $0.00 | BYO telephony = free |
| Total (Haiku + Retell Twilio UK) | ~$0.19/min | |
| Total (Haiku + Custom telephony) | ~$0.09/min | |
| Total (Sonnet + Custom telephony) | ~$0.13/min |
VAPI All-In Cost (Estimated)
VAPI’s pricing page did not render detailed rates. Previous estimates:
| Component | Per Minute |
|---|---|
| Platform fee | $0.05 |
| STT (Deepgram) | ~$0.01 |
| LLM (Claude Sonnet) | ~$0.06 |
| TTS (ElevenLabs) | ~$0.04 |
| Telephony (Twilio) | ~$0.01 |
| Total | ~$0.17/min |
Note: VAPI pricing should be re-verified directly. These are previous estimates.
Voice Cost Per Conversation
Average maintenance call: 3-5 minutes.
| Provider | Config | 3-Min Call | 5-Min Call |
|---|---|---|---|
| Retell (Haiku + custom telephony) | Budget | $0.27 | $0.45 |
| Retell (Sonnet + custom telephony) | Quality | $0.39 | $0.65 |
| Retell (Haiku + Retell Twilio UK) | Default | $0.57 | $0.95 |
| VAPI (est.) | Default | $0.51 | $0.85 |
Voice is 10-20× more expensive per interaction than chat/WhatsApp. Channel mix matters enormously for cost.
Voice Pricing Model Options
Given voice costs $0.27-0.95 per call, including it in a flat per-unit fee creates margin risk. Options:
| Model | How It Works | Pros | Cons |
|---|---|---|---|
| Tier-gated | Voice only on Premium/Partner (£5+/unit) | Protects Basic margins; upsell lever | Limits adoption of best demo feature |
| Usage-based add-on | Base plan + voice at £0.10-0.15/min billed to org | Perfect cost alignment; transparent | Unpredictable bills; friction |
| Included with cap | e.g. 5 voice minutes/unit/mo on Premium, overage at cost | Predictable for customer; capped risk | Still subsidising voice |
| Per-call flat fee | e.g. £0.50/call charged to org | Simple to understand | May discourage usage |
Recommendation: Voice as a Premium/Partner tier feature with an included cap (e.g. 5 min/unit/mo). This:
- Keeps Basic tier margins healthy (no voice subsidy)
- Creates a strong upsell path (“upgrade to get the AI phone line”)
- Caps Envo’s exposure on heavy voice users
- Aligns with the pricing analysis recommendation (voice in Premium at £5/unit)
For Partner-tier BYOAK orgs, they bring their own VAPI/Retell account — voice cost shifts entirely to them.
Impact on Scaling Model
If voice is tier-gated (not in Basic), the cost milestones change significantly:
| Scale | With voice in all tiers | Voice in Premium/Partner only (est. 30% of properties) |
|---|---|---|
| 500 props | $52/mo | ~$16/mo |
| 1,000 props | $104/mo | ~$31/mo |
| 3,000 props | $312/mo | ~$94/mo |
Moving voice to Premium saves ~$218/mo at 3K scale.
6. Stripe Payments Integration
When billing is implemented (ADR-004):
Stripe Fees (Verified 2026-02-23)
| Fee Type | Rate |
|---|---|
| UK standard card processing | 1.5% + 20p per transaction |
| UK premium card processing | 1.9% + 20p |
| EEA cards | 2.5% + 20p |
| International cards | 3.25% + 20p |
| Stripe Billing (subscriptions) — pay-as-you-go | +0.7% per recurring payment |
| Stripe Billing (annual contract) | From £450/mo |
| Stripe Connect (if marketplace) | Starting at 0.25% per transaction |
| Disputes | £20 each |
| Currency conversion | +2% if required |
Example at Scale
Using Stripe Billing pay-as-you-go (0.7% + card processing):
| Scale | Properties | Monthly Revenue (£15/property assumed) | Stripe Fees (est. 2.2% effective) |
|---|---|---|---|
| 50 | 50 | £750 | |
| 500 | 500 | £7,500 | |
| 1,000 | 1,000 | £15,000 | |
| 3,000 | 3,000 | £45,000 |
Note: Effective rate improves at scale because the 20p fixed fee becomes proportionally smaller. Using 2.2% (1.5% card + 0.7% Billing) as base estimate. If most payments are via Direct Debit (Bacs at 1% capped at £4), effective rate could be lower.
Correction from previous version: Stripe Billing is 0.7% pay-as-you-go, not 0.5%. Annual contract option (from £450/mo) may be more cost-effective at scale.
Stripe Connect Consideration
If offering white-label billing where landlords charge their tenants through Envo, Stripe Connect adds 0.25%+ per transaction. This is relevant for the Partner tier (ADR-014).
7. White-Labelling Cost Implications (ADR-014)
Cost Shifts by Tier
| Tier | Cost Impact |
|---|---|
| Basic | All costs on Envo’s shared accounts |
| Premium (BYOAK) | Org pays own Resend + LLM → Envo’s variable costs drop |
| Partner (full white-label) | Org pays own Twilio + VAPI + LLM → Envo’s costs are nearly fixed only |
BYOAK Cost Savings for Envo
When a Premium/Partner org brings their own API keys:
- LLM costs shift to org: saves ~$0.02-0.06 per conversation
- Email costs shift to org: saves ~$20/mo per org
- Twilio costs shift to org: saves ~$0.05-0.26 per notification
White-Label Infrastructure Costs
| Feature | Cost to Envo |
|---|---|
| Custom domains (Partner) | Cloudflare custom hostname — included in Workers plan |
| Supabase Vault (credential storage) | Included in Supabase Pro |
| SSO/SAML (Partner) | Depends on provider — Supabase Auth supports SAML on Team plan ($599/mo) |
Key Risk: Supabase SAML
SSO/SAML is only available on Supabase Team plan (25/mo). Consider whether SSO can be handled at the Cloudflare Access layer instead (which supports SAML on paid plans).
8. Scaling Model — Full Cost at Milestones
Assumptions
- Issues per property per month: 1.5 (HMO avg)
- Conversations per property per month: 2 (issues + Q&A)
- Messages per conversation: 6
- Notifications per issue: 5 (SMS + email mix)
- Voice calls: 10% of conversations
- Avg voice call duration: 4 minutes
- Documents per property: 5 (one-time ingestion)
- Channel mix: 60% WhatsApp, 30% chat, 10% voice
- Dashboard users: 1 per 50 properties (staff + landlords)
Dev / Now (0-5 Properties)
| Cost Centre | Monthly |
|---|---|
| Cloudflare Workers Paid | $5.00 |
| Supabase Pro* | $25.00 |
| Resend (Free tier — <100 emails/day) | $0.00 |
| Domain (amortised) | $0.83 |
| Terraform Cloud | $0.00 |
| Twilio phone number (1 UK number) | ~$1.15 |
| LLM / AI (minimal testing) | ~$0.50 |
| Twilio SMS / WhatsApp | ~$1.00 |
| Total | ~$34 |
* Currently on Supabase Free — actual dev cost is ~$8/mo. Will upgrade to Pro before real users.
50 Properties
| Cost Centre | Monthly |
|---|---|
| Cloudflare (Workers + Pages + Hyperdrive + DNS) | $5 |
| Supabase Pro (DB ~1 GB, Auth ~50 MAUs, Storage ~5 GB) | $25 |
| Resend Free (1,500 emails/mo — within 3K/mo limit) | $0 |
| Twilio phone numbers (2 UK) | $2.30 |
| LLM — Claude Sonnet (100 convos × $0.04) | $4 |
| LLM — OpenAI embeddings (250 docs × $0.001) | $0.25 |
| Twilio SMS (75 issues × 5 notifications × $0.0524) | $19.65 |
| Twilio WhatsApp (60 convos × $0.10) | $6 |
| Voice AI (10 calls × 4 min × $0.13) | $5 |
| Supabase Storage (issue attachments ~2 GB) | $0 (within 100 GB) |
| $0 (ZTNA removed when public) | |
| Infra + variable total | ~$67 |
| + Stripe fees (£750 revenue × ~2.2%) | |
| Grand total | ~$88 |
Note: At 50 properties, Resend Free tier may suffice (est. 1,500 emails/mo < 3K limit). But the 100/day limit could be tight on busy days — upgrade to Pro (88.
500 Properties
| Cost Centre | Monthly |
|---|---|
| Cloudflare (Workers + Pages + Hyperdrive) | $5 |
| Supabase Pro (DB ~4 GB, Auth ~200 MAUs, Storage ~25 GB) | $25 |
| Supabase compute upgrade (Small) | $25 |
| Resend Pro (~15K emails/mo) | $20 |
| Twilio phone numbers (3 UK) | $3.45 |
| LLM — Claude Sonnet (1,000 convos × $0.04) | $40 |
| LLM — OpenAI embeddings (queries, negligible) | $1 |
| Twilio SMS (750 issues × $0.26 per lifecycle) | $195 |
| Twilio WhatsApp (600 convos × $0.10) | $60 |
| Voice AI (100 calls × 4 min × $0.13) | $52 |
| Supabase Storage (attachments + docs ~20 GB) | $0 (within 100 GB) |
| $0 (ZTNA removed when public) | |
| Infra + variable total | ~$427 |
| + Stripe fees (£7,500 revenue × ~2.2%) | |
| Grand total | ~$636 |
1,000 Properties
| Cost Centre | Monthly |
|---|---|
| Cloudflare (Workers + Pages + Hyperdrive) | $5 |
| Supabase Pro (DB ~10 GB, Auth ~400 MAUs, Storage ~50 GB) | $25 |
| Supabase DB overage (2 GB × $0.125) | $0.25 |
| Supabase compute upgrade (Medium) | $50 |
| Resend Pro (~30K emails/mo) | $20 |
| Twilio phone numbers (5 UK) | $5.75 |
| LLM — Claude Sonnet (2,000 convos × $0.04) | $80 |
| LLM — OpenAI embeddings | $2 |
| Twilio SMS (1,500 issues × $0.26) | $390 |
| Twilio WhatsApp (1,200 convos × $0.10) | $120 |
| Voice AI (200 calls × 4 min × $0.13) | $104 |
| Supabase Storage (attachments + docs ~40 GB) | $0 (within 100 GB) |
| $0 (ZTNA removed when public) | |
| Infra + variable total | ~$802 |
| + Stripe fees (£15K revenue × ~2.2%) | |
| Grand total | ~$1,220 |
3,000 Properties (Target Scale)
| Cost Centre | Monthly |
|---|---|
| Cloudflare (Workers ~5M req/mo + Pages + Hyperdrive) | $5 |
| Supabase Pro (DB ~25 GB, Auth ~800 MAUs, Storage ~120 GB) | $25 |
| Supabase DB overage (17 GB × $0.125) | $2.13 |
| Supabase Storage overage (20 GB × $0.021) | $0.42 |
| Supabase bandwidth overage (est. 50 GB over) | $4.50 |
| Supabase compute upgrade (Large) | $100 |
| Resend Scale (~80K emails/mo, need dedicated IP) | $90 |
| Twilio phone numbers (10 UK) | $11.50 |
| LLM — Claude Sonnet (6,000 convos × $0.04) | $240 |
| LLM — Claude Haiku reranking (ADR-018) | $36 |
| LLM — OpenAI embeddings | $5 |
| Twilio SMS (4,500 issues × $0.26) | $1,170 |
| Twilio WhatsApp (3,600 convos × $0.10) | $360 |
| Voice AI (600 calls × 4 min × $0.13) — Premium/Partner only | $312 |
| $0 (ZTNA removed when public) | |
| Terraform Cloud (~15 resources × $0.10) | $1.50 |
| Infra + variable total | ~$2,363 |
| + Stripe fees (£45K revenue × ~2.2%) | |
| Grand total | ~$3,616 |
If voice is tier-gated (Premium/Partner only, ~30% of properties): voice drops to ~2,145.
9. Cost Breakdown by Category (at 3,000 Properties)
With ZTNA removed (app is public) and voice as Premium/Partner only:
| Category | Monthly | % of Total |
|---|---|---|
| Twilio (SMS + WhatsApp) | $1,542 | 65% |
| Voice AI (Premium/Partner only) | $312 | 13% |
| LLM (Claude + OpenAI) | $281 | 12% |
| Supabase (DB + Auth + Storage + Compute) | $132 | 6% |
| Resend | $90 | 4% |
| Other fixed (CF Workers, domain, TF) | $7 | <1% |
| Total | ~$2,363 |
Twilio is the dominant cost at scale — nearly two-thirds of total costs. This makes the WhatsApp migration path (Twilio → direct Meta API) and SMS → WhatsApp notification shift the two highest-impact optimisations.
Where Each Dollar Goes (per property per month at 3K)
| Category | Per Property |
|---|---|
| Twilio SMS (notifications) | $0.39 |
| Twilio WhatsApp (conversations) | $0.12 |
| Voice AI (if Premium/Partner) | $0.10 |
| LLM (generation + reranking) | $0.09 |
| Supabase | $0.04 |
| Resend | $0.03 |
| Other | <$0.01 |
| Total infra per property | $0.79 |
| + Stripe pass-through | $0.42 |
With Optimisations Applied
If you shift SMS notifications to WhatsApp where possible and migrate to direct Meta API:
| Optimisation | Saving at 3K |
|---|---|
| SMS → WhatsApp for tenant notifications (~60% shift) | -$450/mo |
| Twilio → Direct Meta API ($0.005/msg markup removed) | -$180/mo |
| Optimised total | **~0.58/property) |
10. Supabase Cost Deep-Dive: Storage Migration & Scaling
Supabase Storage is currently used for three buckets: issue-attachments, property-documents, and chat-uploads. At scale, this becomes a meaningful cost centre. Here’s a detailed analysis of whether migration makes sense.
Current Storage Architecture
| Bucket | File Size Limit | Est. Growth Rate | At 3K Properties |
|---|---|---|---|
| issue-attachments | 10 MB | ~5 MB/issue × 1.5 issues/prop/mo | ~27 GB/year growth |
| property-documents | 20 MB | ~5 docs × 2 MB/doc = 10 MB/prop (one-time) | ~30 GB (one-time, then slow growth) |
| chat-uploads | 5 MB | ~0.5 MB/conversation avg | ~18 GB/year growth |
| Total at 3K after Year 1 | ~75 GB | ||
| Total at 3K after Year 2 | ~120 GB (exceeds 100 GB included) |
When Storage Becomes a Cost Issue
| Time | Est. Total Storage | Supabase Cost | Overage |
|---|---|---|---|
| Year 1 at 3K | ~75 GB | $0 (within 100 GB) | None |
| Year 2 at 3K | ~120 GB | 0.021) | Minimal |
| Year 3 at 3K | ~165 GB | 0.021) | Still cheap |
| Year 3 at 3K + heavy use | ~250 GB | 0.021) | Manageable |
Key finding: Supabase Storage overage at 3.15/mo. The storage cost is not a significant scaling concern.
Bandwidth/Egress Is the Real Risk
Storage costs are cheap, but downloading files is where costs scale:
| Scenario | Monthly Egress | Supabase Cost |
|---|---|---|
| Dashboard users viewing attachments (low) | ~50 GB | $0 (within 250 GB) |
| Dashboard users + tenant-facing docs (medium) | ~200 GB | $0 (within 250 GB) |
| Heavy API usage + document serving (high) | ~500 GB | 0.09) |
| CDN-less direct serving at scale | ~1 TB | $67.50/mo |
Migration Options: Should We Move Storage?
| Option | Storage Cost | Egress Cost | Pros | Cons |
|---|---|---|---|---|
| Stay on Supabase Storage (current) | $0.021/GB | $0.09/GB after 250 GB | Simple, integrated, RLS policies, no migration needed | Egress costs at very high scale |
| Cloudflare R2 | $0.015/GB/mo | $0 egress | Zero egress costs, same Cloudflare ecosystem | Separate integration, no RLS, need signed URLs |
| Cloudflare R2 + Supabase proxy | $0.015/GB/mo | $0 egress | Best of both: zero egress + Supabase auth layer | Complexity of proxy setup |
| S3 + CloudFront | $0.023/GB/mo | $0.085/GB | Industry standard, mature | AWS complexity, vendor sprawl |
Recommendation: Stay on Supabase, Plan R2 Migration at 3K+
-
Now → 1,000 properties: Stay on Supabase Storage. Costs are negligible ($0-3/mo for storage). Egress stays within 250 GB included.
-
1,000-3,000 properties: Monitor egress. If dashboard + API traffic pushes egress past 300-400 GB/mo, begin R2 evaluation.
-
3,000+ properties: Migrate property-documents and issue-attachments to Cloudflare R2. Keep chat-uploads on Supabase (small files, tightly coupled to conversations).
- R2 at 3K properties (120 GB storage): 0 egress vs Supabase ~22.50/mo egress = saves $0-24/mo.
- Not worth the migration effort below 3K properties unless egress becomes a problem.
-
Alternative: Put Cloudflare CDN in front of Supabase Storage URLs (cache at edge, reduce egress). This is the lowest-effort option and may defer R2 migration indefinitely.
Supabase Cost Scaling Summary
| Scale | DB (disk) | Storage | Compute | Egress | Auth | Total Supabase |
|---|---|---|---|---|---|---|
| Dev (0-5) | $0 (within 8 GB) | $0 (within 100 GB) | Included (Micro) | $0 (within 250 GB) | $0 (within 100K MAU) | $25 (Pro base) |
| 50 | $0 | $0 | Included | $0 | $0 | $25 |
| 500 | $0 (~4 GB) | $0 (~25 GB) | $25 (Small) | $0 (~100 GB) | $0 (~200 MAU) | $50 |
| 1,000 | $0.25 (10 GB, 2 GB over) | $0 (~50 GB) | $50 (Medium) | $0 (~200 GB) | $0 (~400 MAU) | $75 |
| 3,000 | $2.13 (25 GB, 17 GB over) | $0.42 (120 GB, 20 GB over) | $100 (Large) | $4.50 (300 GB, 50 GB over) | $0 (~800 MAU) | $132 |
Supabase compute is the dominant Supabase cost — not storage, not egress, not DB size. At 3K properties, compute is 76% of the total Supabase bill.
Supabase Compute Optimisation Strategies
| Strategy | Potential Saving | Effort |
|---|---|---|
| Connection pooling via Hyperdrive | Already done — prevents connection exhaustion | Done |
| Read replicas (Supabase add-on) | Offload reads, keep smaller primary compute | Medium |
| Query optimisation (indexes, N+1 prevention) | Can delay compute upgrades by 30-50% | Ongoing |
| Cache hot queries (Redis/KV at edge) | Reduce DB load significantly | Medium-High |
| Migrate to self-managed Postgres (Neon, Railway, etc.) | More control over compute costs | High (lose Supabase Auth/Storage/RLS) |
Recommendation: Optimise queries and use Hyperdrive (already done) before upgrading compute. Add read replicas at 1K+ properties if primary becomes bottleneck. Do not migrate off Supabase — the integrated Auth + Storage + RLS + Vault is worth the compute premium.
11. Key Sensitivities
| Variable | Impact |
|---|---|
| Voice call volume | +10% voice adoption = +$360/mo at 3K scale |
| Issues per property | Each +0.5 issues/property/mo = +80 LLM at 3K |
| WhatsApp vs SMS mix | Shifting notifications from SMS → WhatsApp saves ~50-70% |
| Twilio → Direct Meta API | Removes 180/mo at 3K |
| BYOAK adoption | Premium/Partner orgs shifting own keys saves $0.04+/conversation |
| Claude model choice | Haiku vs Sonnet = 3× cheaper LLM costs |
| Voice pricing model | Tier-gating voice to Premium saves ~$218/mo vs including in all tiers |
| SMS rate increase | Twilio UK SMS is 0.046) — 14% increase affects all SMS projections |
| Stripe Billing fee | 0.7% pay-as-you-go (up from previously assumed 0.5%) — affects payment projections |
| Supabase compute | Largest Supabase cost — query optimisation can delay upgrades significantly |
12. Recommendations: DB Data for Better Estimates
To replace these back-of-envelope numbers with real data, query the dev DB for:
Conversation Metrics
-- Average messages per conversation
SELECT
AVG(msg_count) AS avg_messages,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY msg_count) AS median_messages,
PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY msg_count) AS p95_messages
FROM (
SELECT conversation_id, COUNT(*) AS msg_count
FROM messages
GROUP BY conversation_id
) t;
-- Conversations per property per month
SELECT
DATE_TRUNC('month', c.started_at) AS month,
c.property_id,
COUNT(*) AS conversations
FROM conversations c
WHERE c.property_id IS NOT NULL
GROUP BY 1, 2;
-- Channel distribution
SELECT channel, COUNT(*) AS count,
ROUND(COUNT(*)::NUMERIC / SUM(COUNT(*)) OVER () * 100, 1) AS pct
FROM conversations
GROUP BY channel;Issue Metrics
-- Issues per property per month
SELECT
DATE_TRUNC('month', created_at) AS month,
property_id,
COUNT(*) AS issues
FROM issues
WHERE deleted_at IS NULL
GROUP BY 1, 2;
-- Notifications per issue (from issue_events)
SELECT
ie.issue_id,
COUNT(*) FILTER (WHERE ie.event_type = 'NOTIFICATION_SENT') AS notifications
FROM issue_events ie
GROUP BY ie.issue_id;Voice Metrics
-- Voice conversation duration
SELECT
AVG(m.audio_duration_seconds) AS avg_seconds,
SUM(m.audio_duration_seconds) AS total_seconds,
COUNT(DISTINCT m.conversation_id) AS voice_conversations
FROM messages m
JOIN conversations c ON m.conversation_id = c.id
WHERE c.channel = 'VOICE'
AND m.audio_duration_seconds IS NOT NULL;Storage Metrics
-- Total document storage
SELECT
COUNT(*) AS total_docs,
SUM(file_size) / 1024 / 1024 AS total_mb,
AVG(file_size) / 1024 AS avg_kb
FROM property_documents
WHERE deleted_at IS NULL;
-- Chunks per document (for embedding cost)
SELECT
AVG(chunk_count) AS avg_chunks,
MAX(chunk_count) AS max_chunks
FROM (
SELECT document_id, COUNT(*) AS chunk_count
FROM document_chunks
GROUP BY document_id
) t;
-- Attachment storage
SELECT
COUNT(*) AS total_attachments,
SUM(file_size) / 1024 / 1024 AS total_mb
FROM attachments;Token Usage (If Logged)
If you instrument LLM calls to log token counts:
-- Average tokens per conversation
-- (requires adding a token_usage table or JSONB field to messages)Recommendation: Add a token_usage JSONB column to the messages table for AI-role messages, storing { input_tokens, output_tokens, model, cost_usd }. This enables accurate cost tracking per conversation.
13. Cost Optimisation Levers
| Lever | Saving | Effort |
|---|---|---|
| Use Haiku for orchestration (ADR-017 already plans this) | 3× cheaper LLM costs | Low |
| Shift SMS → WhatsApp where possible | ~50% per notification | Medium |
| Email digest for non-urgent (ADR-005) | Reduces SMS volume significantly | Medium |
| Prompt caching (Anthropic) | Up to 90% on repeated system prompts | Low |
| Context compression (ADR-018) | 40-60% token reduction | Medium |
| BYOAK for large orgs (ADR-014) | Variable costs shift to customer | High |
| Batch embeddings (OpenAI Batch API) | 50% off embedding costs | Low |
| Negotiate Twilio volume pricing | 10-30% at scale | Low (just ask) |
| Cloudflare CDN for Supabase Storage | Reduce egress costs at scale | Low |
| R2 migration for large files | Eliminate egress at 3K+ properties | Medium |
| Read replicas (Supabase) | Delay compute upgrades | Medium |
| Query optimisation + DataLoader | Delay compute upgrades by 30-50% | Ongoing (partially done) |
| Resend Free tier | $0 email cost up to 3K emails/mo | Already available |
14. Action Items
Immediate
- Instrument LLM calls with token counting (add
token_usageJSONB to messages table) - Set up Anthropic/OpenAI spend alerts
- Decide on VAPI vs Retell (Retell is ~30% cheaper with custom telephony)
- Add
external_billing_idto organisations table (ADR-004) - Replace
@sendgrid/mailwith Resend SDK inpackage.json - Upgrade Supabase to Pro plan before real users
Before 500 Properties
- Plan WhatsApp BSP migration: Twilio → direct Meta Cloud API (saves $0.005/msg)
- Shift SMS notifications to WhatsApp where tenant is already on channel (50-70% cost reduction)
- Run DB queries (section 12) against real data to validate assumptions
- Get Twilio volume pricing quote
- Monitor Supabase egress — plan CDN or R2 if approaching 250 GB/mo
Before 1,000 Properties
- Implement direct Meta WhatsApp Business API integration
- Finalise voice pricing model (tier-gated vs usage-based add-on)
- Feed per-property cost into Business Model pricing — break-even is ~$1.50-2/property/mo with optimisations
- Evaluate Supabase read replicas if compute is bottleneck
Before 3,000 Properties
- Consider Cloudflare R2 for property-documents and issue-attachments (zero egress)
- Evaluate Stripe Billing annual contract vs pay-as-you-go (£450/mo vs 0.7%)
- Consider Supabase Team plan ($599/mo) only if SAML is required for Partner tier
- Revisit Resend Scale (0.10/1K) for email at high volume
Resolved
-
Plan for Cloudflare Access 50-user cliff— ZTNA will be removed when app goes public (Terraform destroys Access app + policy) -
n8n cloud/self-hosted decision— n8n is no longer required. Removed from service inventory. -
SendGrid vs alternative— Decided on Resend. Better free tier, modern DX, competitive pricing.
Note: Vercel → Cloudflare Migration
The earlier Capacity Analysis and Pricing Analysis reference Vercel as the hosting layer. The dashboard has since migrated to Cloudflare Workers via @opennextjs/cloudflare. This analysis uses the current Cloudflare pricing. Key differences:
- Cloudflare Workers Paid: **20/mo per team member)
- Includes Hyperdrive connection pooling, Pages, and DNS at no extra cost
- No per-function invocation charges (included in 10M requests/mo)
- Static assets are free and unlimited (not counted against request quota)
This makes hosting cheaper than the session docs estimated.
Related
- Business Model
- Capacity Analysis (Session 1 — references Vercel, now on Cloudflare)
- Pricing Analysis (Session 2 — competitor pricing + tier recommendations)
- ADR-004 Billing Integration
- ADR-005 Notification Preferences
- ADR-014 White-Label & BYOAK
- ADR-017 RAG Pipeline v2
- ADR-018 RAG Context Management
- Tech Stack