Skip to content

System Architecture

The Kaya Sync platform is built on an event-driven, multi-tenant architecture. At MVP scale, every service runs co-located on a single Hetzner CX22 box behind Cloudflare's edge; services split out to dedicated hosts only when traffic or compliance justify it.

For the cost rationale, free-tier verdict, capacity headroom and full capability-to-service mapping, see Hosting & Data Plan.


Topology at a glance

┌────────────────────────────────────────────────────────────────────┐
│                       Cloudflare (free edge)                       │
│   DNS · TLS · DDoS · Turnstile · Web Analytics · Email Routing     │
│                                                                    │
│   kayasync.com         wiki.kayasync.com    cdn.kayasync.com (R2)  │
│   app.kayasync.com     admin.kayasync.com                          │
└──────────────┬─────────────────────────────────────────────────────┘
               │  HTTPS

┌────────────────────────────────────────────────────────────────────┐
│           Hetzner CX22 (2 vCPU · 4 GB · €3.79/mo)                  │
│           Single host, Docker Compose                              │
│                                                                    │
│   Caddy (reverse proxy + auto-TLS)                                 │
│     │                                                              │
│     ├── Hono API (TypeScript) — backend microservices              │
│     ├── Python FastAPI sidecar — OCR + video AI                    │
│     │                                                              │
│     ├── Postgres — event store + transactional state + audit log   │
│     ├── Redis    — rate limits, sessions, dedupe, telemetry buffer │
│     └── NATS     — event bus / pub-sub (JetStream persistence)     │
└────────────────────────────────────────────────────────────────────┘
               ▲                                          ▲
               │ background sync                          │ FCM push
               │                                          │
┌──────────────┴──────────────────────────┐  ┌────────────┴──────────┐
│   React Native operator app             │  │  Firebase Cloud       │
│   On-device TF Lite for fingerprint     │  │  Messaging (free)     │
│   Offline-first capture + sync queue    │  │                       │
└─────────────────────────────────────────┘  └───────────────────────┘

Core services (logical)

The platform is conceptually 12 services per Port Allocation. At MVP they run as modules inside a single Hono process; the port map governs how they split out later.

ServiceOwnsSplits out when
Identity & AccessOperator/originator accounts, JWT issue, RBACMulti-region deployment needs local issuance
Device GovernanceDevice binding, attestation, trust tierMobile install base > ~5,000 active devices
Vehicle & CapacitySOD attestation, vehicle profile, capacity inferenceCapacity-AI inference becomes a bottleneck
Order & ContainerOrder lifecycle, container state machine, multi-leg routingOrder volume > 10k/day
Scan IngestionUpload pre-signing, scan record creation, dedupeMedia volume saturates a single host's bandwidth
Integrity AIServer-side OCR, fingerprint match, geo / time validationNeed a GPU host for batch ML
OrchestrationAggregation/disaggregation scoring, dispatcher queueReal-time scoring needs > 1 CPU sustained
SettlementEligibility check, HOLD/RELEASE/REVERSE workflow, payout dispatchSettlement volume warrants finance-isolated host
Carbon LedgerPer-journey carbon calc, ESG exportPartner reporting volume warrants own host
Fraud & CollusionReplay/duplicate/dyad/relabel detection, risk flagsDetection model needs a dedicated worker
Audit / Event StoreAppend-only event ledger, custody chain reconstructionEvent volume saturates Postgres write capacity
NotificationSMS, push, USSD, in-app, email fan-outHigh concurrency or per-channel scaling

All 12 services share one Postgres schema at MVP. The split-out trigger is volume or compliance, not architectural purity.


Runtime stack

LayerChoiceWhy
Backend HTTP/WSTypeScript on HonoRuns identically on Cloudflare Workers and Node — strategic optionality. Team already TS-first.
AI / OCR / videoPython on FastAPICV/ML ecosystem (PaddleOCR, OpenCV, MediaPipe) non-negotiable in Python
MobileReact Native + TensorFlow LiteShared types with backend; on-device fingerprint + replay detection aligned with offline-first principle
Internal admin / client portalNext.js or AstroStatic where possible, behind Cloudflare Access (free ≤ 50 users)
Reverse proxy / TLSCaddySingle binary, auto-TLS, no manual renewal
DBPostgresEvent store + transactional state + audit log in one engine
Cache / rate / sessionsRedisSelf-hosted; Upstash free as edge backup
Event busNATS (with JetStream)Single binary, < 50 MB RAM, pub/sub + durable streams. Kafka is overkill at MVP, MQTT only if mobile talks to it directly.
Object storageCloudflare R2Zero egress — the right home for scan media served back to enterprises/regulators
PushFirebase Cloud MessagingUnlimited free
SMS / USSDAfrica's TalkingBest Ghana coverage, has USSD
Mobile moneyFlutterwaveBest Africa-wide coverage
Transactional emailResendAlready wired (lead form); 3K/mo free

Data flow — origin scan example

  1. Operator captures origin scan video on the mobile app (offline-capable, encrypted at rest)
  2. On reconnect, mobile requests a presigned upload URL from the Hono API (/scans/upload-url)
  3. Mobile uploads directly to R2 (presigned URL, 900 s validity)
  4. Mobile notifies the API the upload is complete (/scans/:id/submit)
  5. API publishes a scan.uploaded event to NATS
  6. Scan Ingestion subscriber validates the upload, writes the scan record to Postgres
  7. Integrity AI subscriber:
    • Pulls the video from R2
    • Sends to the Python FastAPI sidecar for OCR + fingerprint
    • Writes the integrity result + reason codes to Postgres
    • Publishes scan.assessed event
  8. Order/Container subscriber transitions container state per State Model
  9. Notification subscriber fans out SMS/push to originator + operator
  10. Every transition becomes a row in the audit/event ledger — see Acceptance Criteria §15

Total round-trip target: < 5 s under normal load, async beyond that — settlement is never blocked on upload latency.


Pages in this section

  • Hosting & Data Plan — full cost rationale, capability mapping, phasing
  • Port Allocation — port map for when services split out
  • Service boundaries & APIs — to be added per service as designs are completed
  • Data model & database schema — to be added
  • Authentication & access control — to be added

Kaya Sync Internal Documentation