Overview

One Cloud Run service, many backends

The console is a single stateless Node container. State lives in managed services, so it scales to zero and back without losing anything. Notifications run separately as event-driven Cloud Functions.

Request path

Cloudflare

TLS, CDN, WAF in front of the custom domain

Cloud Run

Node + Express, EJS views, Alpine.js islands

Session

Firestore-backed cookie + Bearer JWT for API

Stateless container: any replica can serve any request; nothing is kept in process memory that matters across requests except short-lived caches.

Backing services

ServiceRoleWhy this one
BigQueryAnalytics warehouse + campaign log + MLCheap columnar scans; ARIMA_PLUS for anomalies
MongoDB (Atlas)Campaign audience readsRead replica avoids the inflated warehouse mirror that would double campaign cost
FirestoreMobile event source of truthReal-time triggers + authoritative conversion facts
Cloud TasksScheduled campaignsSurvives scale-to-zero; fires future jobs reliably
Cloud StorageCreative assets (private)Signed URLs for external consumers; no public objects
Secret ManagerCredentialsNo secrets in the image or env literals in source
Cloud FunctionsNotificationsIndependent lifecycle; reacts to Firestore writes

Data flows

Inbound

WhatsApp / Instagram / Messenger webhooks land on the console; chat threads persist to the warehouse.

Scheduled ETL

Cloud Scheduler triggers hourly pulls from Meta Ads, GA4 and Firestore into BigQuery.

Outbound

Campaigns fan out to the WhatsApp Cloud API; push goes through Cloud Functions to FCM / HMS.

Relay - anonymized engineering case study.