Appearance
Hosting & Data Plan
Document type: Engineering Plan — Hosting & Data Status: Approved Last updated: 2026-05-24
This page captures the decisions the platform needs to start building: where code runs, where data lives, what messaging/queue layer we use, and what language the backend is written in. It supersedes section 8 of the Kick-off Plan.
Note (Aug 2026): infrastructure has moved from Hetzner to DigitalOcean to consolidate billing and remove SRE burden via managed data services. The platform now exposes two API surfaces from day 1 —
core.kayasync.com(internal clients) andapi.kayasync.com(external customers). Compute runs on DO App Platform (core + api + ai-sidecar) + a DO Droplet (dispatch + location + NATS), with DO Managed Postgres Production (auto-failover) + Managed Redis. Cloudflare stays as the free edge, and R2 stays for object storage (zero egress wins vs DO Spaces). MVP tier lands at ~$365/mo all-in — DO subtotal ~$221 + observability/error/security/secrets stack ~$144. See System Architecture for the canonical topology, API surface, and full cost breakdown. This page's Cloudflare free-tier rationale still stands; the specific box counts and Hetzner references in "Recommended architecture" § 2 and the Phasing table below are superseded.
TL;DR
- Cloudflare's free tier alone is not enough to run the platform end-to-end. It is enough for the marketing site, the wiki, and the public edge (DNS, TLS, DDoS, R2 media).
- The platform runs on DigitalOcean at MVP: DO App Platform for
core,api, and the AI sidecar; a DO Droplet (s-2vcpu-4gb) forlocation-svc+dispatch-svc+ NATS + Caddy; DO Managed Postgres Production (auto-failover) + Managed Redis 2 GB. Cloudflare stays as the free edge. - Backend languages: TypeScript on Hono for
core+apiHTTP surfaces, Go for the WSS location + dispatch services, Python (FastAPI) for the AI/ML sidecar only. - Total cost at MVP: ~$371/mo all-in (~$227 DO subtotal + ~$144 observability / error / edge-security / secrets stack) + per-txn SMS and mobile-money fees. See System Architecture → Cost model for the line-by-line breakdown and the Stage 2/3/4 trajectory.
Why not "everything on Cloudflare free"
Three load-bearing reasons:
- Free Workers is 100,000 requests/day total. Telemetry heartbeats alone exhaust this in minutes — see Operator Journey §5.1. At 1 heartbeat / 30 s × 100 active operators × 16 h/day = ~192,000 req/day. Pilot scale is already over the cap.
- Cloudflare Queues require the Workers Paid plan ($5/mo minimum). There is no free Queues tier. The platform is explicitly event-driven — see Governing Assumptions: "Event-driven governance — each meaningful action must generate an event". A real queue is non-negotiable.
- Cloudflare has no Redis, no MQTT, no Kafka. The closest free analogues are KV (eventually consistent, 1K writes/day on free) and Durable Objects (paid plan only). The free tier cannot host the messaging/queue layer the platform's state machine needs.
Adjacent constraints that matter even on paid Cloudflare:
| Service | Free tier | Why it bites us |
|---|---|---|
| Workers (free) | 100K req/day | Telemetry exhausts this |
| Workers Logs (free) | 200K events/day, 3-day retention | Not enough for an event-sourced audit log |
| D1 (free) | 5 GB, 5M reads/day, 100K writes/day | Audit + telemetry + events exceed it fast |
| R2 (free) | 10 GB, 1M Class-A, 10M Class-B/mo, zero egress | At ~3 MB/scan video, free tier = ~3,300 scans total — one pilot week |
| Workers AI (free) | 10K neurons/day shared | A single Llama-3.2-vision OCR burns 2,500–5,000 neurons → 2–4 OCRs/day |
| Stream | No free tier | Not used — R2 alone is the right home for raw video |
| Zero Trust / Access | Free up to 50 users | Fine for internal tools, not for thousands of operators |
What does stay free on Cloudflare at meaningful scale:
- DNS / CDN / TLS / DDoS — unlimited, free
- Workers + Pages for static-shape sites (marketing, wiki, admin UI)
- R2 for media (zero egress is the real win vs S3 at $0.09/GB)
- Email Routing (inbound team email, free)
- Turnstile (CAPTCHA, free)
- Web Analytics (cookieless, free)
Recommended architecture
Three layers, three hosts.
1. Edge / public surface — Cloudflare (free everything)
| Surface | Stack | Status |
|---|---|---|
kayasync.com, test.kayasync.com | Astro Worker + static assets | ✅ Live |
wiki.kayasync.com | VitePress + password-gate Worker | ✅ Live |
cdn.kayasync.com | R2 bucket, public read for scan media (egress-free) | ⬜ Pending |
app.kayasync.com, admin.kayasync.com | Next.js 15 (App Router) + React 19, single Turborepo app with RBAC-scoped routing | ⬜ Pending |
Edge services we keep free: DNS, TLS, DDoS, Turnstile, Web Analytics, Email Routing.
2. Backend application + data — DigitalOcean (App Platform + Droplet + Managed Postgres/Redis) [SUPERSEDED — see System Architecture]
Specs: 2 vCPU, 4 GB RAM, 40 GB NVMe, EU data centre, ISO 27001.
Stack — the physical shape has evolved to 5 apps across App Platform + a Droplet. See System Architecture § Core services (logical) for the canonical mapping. Historical single-monolith stack was:
| Component | Role | Notes |
|---|---|---|
Hono (TypeScript) — now split into core.kayasync.com + api.kayasync.com on App Platform | Backend HTTP APIs | Two surfaces from MVP: core for internal clients (admin/mobile/client), api for third-party customers |
Go — location-svc + dispatch-svc on the dispatch droplet | Real-time WSS + geospatial matching | Behind ws.kayasync.com — separated from core because Hono/Node is the wrong runtime for high-concurrency WSS |
| Postgres — now DO Managed Production (auto-failover) | Event store + transactional state + audit log | Single source of truth; TimescaleDB extension for location-history hypertables |
| Redis — now DO Managed Basic 2 GB | GEO index + rate limits + sessions | Managed, no self-host burden |
| NATS JetStream — co-located on the dispatch droplet | Event bus / pub-sub | ~50 MB RAM; Kafka / Redpanda deferred to Stage 3 |
Python FastAPI (ai-sidecar) on App Platform Pro | OCR + heavy AI sidecar | PaddleOCR for phone-number extraction, OpenCV for video frames |
| Caddy on the dispatch droplet | Reverse proxy + auto-TLS for ws.kayasync.com | Single binary, no manual cert renewal |
Capacity headroom: the current tier (see Cost model) is comfortable up to ~1,000 active operators.
Backups: nightly pg_dump → R2 bucket, 30-day retention (belt-and-braces on top of DO Managed Postgres's automated backups + 7-day PITR).
Failover: DO Managed Postgres Production already includes an auto-failover standby node in the same region. Add a second dispatch droplet + DO Load Balancer at Stage 2 (see architecture doc's Stage 2 upgrade list).
3. Mobile app — operator client
- React Native + TensorFlow Lite for on-device fingerprint / replay detection
- All capture flows work offline per Feature Inventory §M9; sync via background queue
- FCM for push (unlimited free), Whisper via Workers AI for voice confirmation (well under 10K neurons/day for short clips)
Capability → service mapping
Comprehensive map for every cross-cutting need in Feature Inventory. "Free?" assumes MVP / first-pilot scale.
| Capability | Recommended service | Free at MVP? |
|---|---|---|
| Marketing site (live) | Cloudflare Workers + static assets | ✅ |
| Internal wiki (live) | Cloudflare Pages + Worker password gate | ✅ |
| 12 backend logical services → 5 physical apps | DO App Platform (core, api, ai-sidecar) + DO Droplet (location-svc, dispatch-svc, NATS, Caddy) — see architecture doc | ~$227/mo DO subtotal |
| Postgres (event store, txn state, multi-tenant) | DO Managed Postgres Production (auto-failover) + TimescaleDB extension | $120/mo |
| Redis (rate limit, session, dedupe, GEO index) | DO Managed Redis Basic 2 GB | $30/mo |
| Message queue / event bus | NATS self-hosted (Postgres LISTEN/NOTIFY for the very first cut) | ✅ |
| Telemetry heartbeat ingestion | Hono /telemetry endpoint, batched, into NATS | ✅ |
| Object storage (video evidence, SOD photos, agreement videos) | Cloudflare R2 | ✅ <10 GB, then $0.015/GB-mo |
| Video AI integrity (fingerprint, replay, tamper) | On-device TensorFlow Lite + server-side Python sidecar | ✅ |
| OCR (designee phone number) | PaddleOCR on the Python sidecar; fall back to Workers AI vision for low-confidence | ✅ |
| Speech-to-text (voice confirmations) | Cloudflare Workers AI Whisper | ✅ |
| Text-to-speech (low-literacy prompts) | Pre-record Prompt Vocabulary as MP3s in R2 | ✅ |
| Authentication (operator phone+OTP, partner SSO) | Hono + JWT + bcrypt against Postgres; SMS OTP via Africa's Talking | ✅ code; SMS paid per msg |
| Push notifications | Firebase Cloud Messaging (unlimited free) | ✅ |
| Transactional email | Resend (already wired, 3,000/mo free) | ✅ |
| Mobile money payouts | Flutterwave (per-txn fees accepted) | n/a |
| Admin / supervisor dashboard | Single Next.js 15 app behind Cloudflare Access (free ≤ 50 users) | ✅ |
| Enterprise client portal (M12) | Same app, different RBAC scope | ✅ |
| Regulator / partner exports (M10, M13) | Postgres view + on-demand CSV/JSON dump | ✅ |
| Observability (logs, metrics, traces) | Grafana Cloud free (10K series, 50 GB logs, 14d) OR self-hosted Grafana + Loki + Prometheus | ✅ |
| Error tracking | Sentry free (5K errors/mo) or self-hosted GlitchTip | ✅ |
| Background / scheduled jobs | Hono cron loop polling NATS / Postgres | ✅ |
Backend language
Primary: TypeScript on Hono
- Runs identically on Cloudflare Workers, Node, Bun, and Deno — strategic optionality for free. Move a handler from Workers to a DO App Platform app (or back) without rewriting.
- Light, modern, Zod-friendly, OpenAPI-ready
- The team is already deep in TS (Astro website, auth-worker) — no language switch needed
- Shared types between mobile (React Native + TS) and backend cut a whole class of bugs
Secondary: Python (FastAPI)
Only for the AI/ML sidecar — OCR (PaddleOCR), video frame analysis (OpenCV), fingerprint extraction. Python's CV/ML ecosystem is not negotiable here. Keep the sidecar small and behind an internal HTTP endpoint.
Future option: Go
If the telemetry ingestor becomes a bottleneck, Go's goroutines + GC profile fit high-fanout streaming better than Node. Don't pre-optimise — only switch when traces show it's needed.
Not recommended
- Rust — wrong cost/benefit for a small team's MVP; revisit if a specific service becomes perf-critical
- Elixir / Phoenix — technically perfect for the real-time dispatcher fanout, but hiring + ecosystem are too thin for a Ghana-based team at MVP. Re-evaluate at 10+ engineers.
- Python as primary — would slow iteration vs TS and force two languages on the frontend anyway
Phasing
Post-migration to DigitalOcean, the phasing model is documented canonically in System Architecture → Cost model → Trajectory across stages. Summary:
| Stage | When | All-in / mo | What's added |
|---|---|---|---|
| MVP recommended | Sep 2026 – Mar 2027 | ~$371 | DO App Platform (core + api + ai-sidecar) + Droplet (location-svc + dispatch-svc + NATS) + Managed Postgres Production + Managed Redis 2 GB + Grafana Cloud Pro + Sentry Team + Cloudflare Pro + 1Password Teams |
| Stage 2 — controlled pilot | Apr – Aug 2027 | ~$550 | Add HA on core (2 instances), second dispatch droplet + DO LB, upgrade Postgres to next tier |
| Stage 3 — regional scale | Sep 2027 – 2028 | ~$1,500 | DOKS (K8s), Redpanda Cloud, second region, dedicated observability stack |
| Stage 4 — Uber-scale | 2029+ | 10K+ | Multi-region active-active, custom matching engine, dedicated SRE team |
Open questions / decisions still to make
- Jurisdiction. DigitalOcean's nearest regions to Ghana are FRA1 (EU) and BLR1/SGP1. If Ghana data-residency rules require West-African hosting, evaluate AWS af-south-1 or a regional partner. Legal to confirm with Enyonam.
- Pilot scale. Concrete numbers from NKA: operators in pilot 1, scans/operator/day, corridors. Re-check R2 / Postgres / dispatch droplet capacity projections once known.
- CF Access seats. Free tier caps at 50 users. When ops-team headcount crosses ~40 (Stage 2), decide between CF Access paid (~$3/user/mo) or self-hosted Zero Trust proxy.
Repo shape (for execution)
When Phase 1 starts, the new monorepo kayasync-platform follows Turborepo per Kick-off Plan §2:
kayasync-platform/
├── apps/
│ ├── api/ # Hono backend
│ ├── admin/ # Internal dispatch/supervisor UI
│ ├── client/ # Enterprise client portal
│ └── mobile/ # React Native operator app
├── services/
│ └── ai-sidecar/ # Python FastAPI (OCR + video AI)
├── packages/
│ └── shared-types/ # Zod schemas shared with mobile + admin
└── infra/
├── docker-compose.yml
├── Caddyfile
└── backup/Sources
Cloudflare: Workers pricing · Workers limits · R2 pricing · D1 pricing · KV pricing · Workers AI pricing · Vectorize pricing · Stream pricing · Zero Trust · Email Routing limits
Alternatives: Hetzner Cloud · Neon Postgres · Supabase · Upstash · Fly.io · Render · Firebase / FCM · Flutterwave Ghana · Africa's Talking Ghana