Skip to content

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) and api.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) for location-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 + api HTTP 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:

  1. 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.
  2. 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.
  3. 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:

ServiceFree tierWhy it bites us
Workers (free)100K req/dayTelemetry exhausts this
Workers Logs (free)200K events/day, 3-day retentionNot enough for an event-sourced audit log
D1 (free)5 GB, 5M reads/day, 100K writes/dayAudit + telemetry + events exceed it fast
R2 (free)10 GB, 1M Class-A, 10M Class-B/mo, zero egressAt ~3 MB/scan video, free tier = ~3,300 scans total — one pilot week
Workers AI (free)10K neurons/day sharedA single Llama-3.2-vision OCR burns 2,500–5,000 neurons → 2–4 OCRs/day
StreamNo free tierNot used — R2 alone is the right home for raw video
Zero Trust / AccessFree up to 50 usersFine 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)

Three layers, three hosts.

1. Edge / public surface — Cloudflare (free everything) ​

SurfaceStackStatus
kayasync.com, test.kayasync.comAstro Worker + static assets✅ Live
wiki.kayasync.comVitePress + password-gate Worker✅ Live
cdn.kayasync.comR2 bucket, public read for scan media (egress-free)⬜ Pending
app.kayasync.com, admin.kayasync.comNext.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:

ComponentRoleNotes
Hono (TypeScript) — now split into core.kayasync.com + api.kayasync.com on App PlatformBackend HTTP APIsTwo surfaces from MVP: core for internal clients (admin/mobile/client), api for third-party customers
Go — location-svc + dispatch-svc on the dispatch dropletReal-time WSS + geospatial matchingBehind 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 logSingle source of truth; TimescaleDB extension for location-history hypertables
Redis — now DO Managed Basic 2 GBGEO index + rate limits + sessionsManaged, no self-host burden
NATS JetStream — co-located on the dispatch dropletEvent bus / pub-sub~50 MB RAM; Kafka / Redpanda deferred to Stage 3
Python FastAPI (ai-sidecar) on App Platform ProOCR + heavy AI sidecarPaddleOCR for phone-number extraction, OpenCV for video frames
Caddy on the dispatch dropletReverse proxy + auto-TLS for ws.kayasync.comSingle 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.

CapabilityRecommended serviceFree at MVP?
Marketing site (live)Cloudflare Workers + static assets✅
Internal wiki (live)Cloudflare Pages + Worker password gate✅
12 backend logical services → 5 physical appsDO 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 busNATS self-hosted (Postgres LISTEN/NOTIFY for the very first cut)✅
Telemetry heartbeat ingestionHono /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 notificationsFirebase Cloud Messaging (unlimited free)✅
Transactional emailResend (already wired, 3,000/mo free)✅
Mobile money payoutsFlutterwave (per-txn fees accepted)n/a
Admin / supervisor dashboardSingle 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 trackingSentry free (5K errors/mo) or self-hosted GlitchTip✅
Background / scheduled jobsHono 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.

  • 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:

StageWhenAll-in / moWhat's added
MVP recommendedSep 2026 – Mar 2027~$371DO 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 pilotApr – Aug 2027~$550Add HA on core (2 instances), second dispatch droplet + DO LB, upgrade Postgres to next tier
Stage 3 — regional scaleSep 2027 – 2028~$1,500DOKS (K8s), Redpanda Cloud, second region, dedicated observability stack
Stage 4 — Uber-scale2029+10K+Multi-region active-active, custom matching engine, dedicated SRE team

Open questions / decisions still to make ​

  1. 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.
  2. Pilot scale. Concrete numbers from NKA: operators in pilot 1, scans/operator/day, corridors. Re-check R2 / Postgres / dispatch droplet capacity projections once known.
  3. 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

Kaya Sync Internal Documentation