Target Architecture
Service decomposition
Section titled “Service decomposition”The monolithic Express server is replaced by three Cloudflare Workers and a static frontend:
| Service | Runtime | Responsibility | Ontological role |
|---|---|---|---|
dashboard-api | CF Worker (Hono) | All CRUD endpoints, dashboard queries, health checks | Primary EngineeredSystem — serves ICEs, Measurement Data, Process Records |
ingest | CF Worker (Queue consumer) | Shopify sync, asset ingest, CSV generation, mart refresh | ProcedureExecution engine — executes all background Procedures |
frontend | CF Pages | React SPA served from edge | Human-agent interface for Persons bearing Roles |
| Shared | Hono middleware + Drizzle | Auth validation, Shopify client, DB access | Cross-cutting EngineeredSystem capabilities |
The dashboard-api and ingest workers communicate via Cloudflare Queues. For direct internal calls (e.g., health aggregation), Service Bindings provide zero-overhead in-Worker communication.
Technology choices
Section titled “Technology choices”| Concern | Choice | Rationale |
|---|---|---|
| Web framework | Hono | Worker-native, middleware ecosystem, TypeScript-first |
| ORM | Drizzle (PostgreSQL dialect) | Already in codebase (Postgres dialect); type-safe, lightweight |
| Database | PlanetScale via Hyperdrive | Managed PostgreSQL, connection pooling at edge |
| Object storage | Cloudflare R2 (binding API) | Replaces @aws-sdk; native Worker access, no credentials |
| Auth | Cloudflare Access | Google SSO, zero-trust, JWT assertion on every request |
| Background jobs | CF Queues + Cron Triggers | Replace Edge Functions; integrated retry, DLQ, scheduling |
| Migrations | dbmate | Framework-agnostic, SQL-native, pairs with PlanetScale branching |
| Frontend hosting | Cloudflare Pages | Edge-served SPA, preview deployments, wrangler integration |
What gets deleted
Section titled “What gets deleted”These dependencies and patterns are removed entirely:
| Removed | Replacement |
|---|---|
express, express-session, connect-pg-simple | Hono |
passport, passport-local | CF Access JWT validation |
@supabase/supabase-js | Drizzle + Hyperdrive |
@aws-sdk/client-s3 | R2 binding API (env.R2_BUCKET.put()) |
@neondatabase/serverless | Hyperdrive connection |
memorystore | N/A (no server-side sessions) |
| All 6 Supabase Edge Functions | Worker queue consumers + cron handlers |
| Supabase RLS policies | CF Access + app-level checks |
| PostgreSQL materialized views | Explicit performance_measurement_dataset table writes |
| Supabase Storage | R2 |
Frontend
Section titled “Frontend”The React frontend changes are minimal:
- Stays: React 18, Vite, shadcn/ui, React Query, Wouter, Recharts, Tailwind
- Changes:
- Remove
@supabase/supabase-jsandAuthContext/AuthProvider - Remove Passport login page — Access handles auth before the app loads
- Replace API client base URL from Express to Worker
- Add
Cf-Access-Jwt-Assertionheader forwarding (automatic when Pages + Workers share a zone)
- Remove
- Deploy: Cloudflare Pages instead of Vercel