DEPLOYMENT_TOPOLOGY — bff-backoffice-service
Sibling: DATA_MODEL · SECURITY_MODEL · SYNC_CONTRACT · LOCAL_DEV_SETUP
Cross-cutting: 02 Enterprise Architecture · §4 GCP Reference Architecture · ADR-0003 Electron offline-first desktop
1. Runtime
| Property | Value |
|---|---|
| Compute | Cloud Run (managed) |
| Region (primary) | asia-south1 (Mumbai) |
| Region (DR-warm) | europe-west4 (Eemshaven) |
| Container | Distroless Node 20, multi-stage build, non-root, read-only root FS |
| Min instances | 2 (per region) |
| Max instances | 20 (per region) |
| Concurrency per instance | 80 |
| CPU | 2 vCPU, always-allocated |
| Memory | 1 GiB |
| Startup latency | < 800 ms |
| Request timeout | 30 s |
| VPC connector | bff-connector-asia-south1 |
2. Ingress
backoffice.melmastoon.ghasi.io (Electron desktop endpoint)
│
▼
Cloud DNS (CNAME → GCLB anycast)
│
▼
Global HTTPS Load Balancer
├── Cloud Armor (per-IP + per-device rules)
├── SNI cert via Certificate Manager
│
▼
Serverless NEG → Cloud Run (bff-backoffice-service)
CDN is off — every endpoint is authenticated and tenant/device-specific. Cache lives at the BFF layer (Memorystore).
3. Egress (upstream)
All upstreams reached over internal Cloud Run-to-Cloud Run via VPC connector with Google ID tokens minted from bff-backoffice-sa.
| Upstream | Hostname | Auth | Timeout | Retries |
|---|---|---|---|---|
iam-service | iam.melmastoon.internal | Google ID token | 600 ms (refresh), 200 ms (validate) | 0 |
tenant-service | tenant.melmastoon.internal | Google ID token | 500 ms | 1 |
reservation-service | reservation.melmastoon.internal | Google ID token | 800 ms (read), 1500 ms (mutation) | 1 mutation |
inventory-service | inventory.melmastoon.internal | Google ID token | 600 ms | 1 |
pricing-service | pricing.melmastoon.internal | Google ID token | 600 ms | 1 |
housekeeping-service | housekeeping.melmastoon.internal | Google ID token | 700 ms | 1 |
maintenance-service | maintenance.melmastoon.internal | Google ID token | 700 ms | 1 |
billing-service | billing.melmastoon.internal | Google ID token | 600 ms | 1 |
lock-integration-service | lock.melmastoon.internal | Google ID token | 1200 ms | 0 (sensitive) |
ai-orchestrator-service | ai.melmastoon.internal | Google ID token | 800 ms | 0 |
notification-service | notification.melmastoon.internal | Google ID token | 500 ms | 1 |
sync-service (handshake only) | sync.melmastoon.internal | Google ID token | 700 ms | 0 |
analytics-service | analytics.melmastoon.internal | Google ID token | 600 ms | 1 |
property-service | property.melmastoon.internal | Google ID token | 800 ms | 1 |
4. Stateful dependencies
| Dependency | Type | Region | HA |
|---|---|---|---|
| Memorystore (Redis 7) — cache tier | bff-backoffice-cache-asia-south1, 5 GiB, standard | asia-south1 | Standby + auto-failover |
| Memorystore (Redis 7) — session tier (no eviction) | bff-backoffice-session-asia-south1, 3 GiB, standard | asia-south1 | Standby + auto-failover |
| Cloud SQL (Postgres 16) | bff-backoffice-db-asia-south1, db-custom-2-8192 | asia-south1 | Regional HA + cross-region replica in europe-west4 |
| Pub/Sub topics | melmastoon.bff.backoffice.* | global | n/a |
| Secret Manager | pepper, sse-signing-key | global | replicated |
5. Electron desktop integration (deployment-side)
The desktop is an independent deployment artifact with its own release pipeline, but its operation depends on this BFF being reachable. Coordination points:
| Concern | Mechanism |
|---|---|
| Backoffice endpoint URL | Hard-coded per-environment in desktop build (prod, stage, dev); over-rideable via signed config update |
| App-version floor | This BFF rejects appVersion < floor with SYNC.VERSION_BLOCKED; floor managed via bff-backoffice-flags Memorystore key with 30 s refresh |
| Auto-update server | Separate (update.melmastoon.ghasi.io); not this BFF |
| Code signing for installers | electron-builder; not this BFF's concern |
contextBridge API surface | Versioned in shared @ghasi/desktop-bridge-types package; consumed by both desktop + this BFF |
| DPoP device key provisioning | First-run flow against iam-service.deviceEnroll; this BFF is on the path only after enrollment |
| MFA factor enrollment | iam-service's responsibility; we only consume attestation tokens |
| Auto-update rollout pacing | Independent of BFF deploys; coordinated via release calendar |
5.1 Compatibility matrix
| Desktop major | BFF major | Status |
|---|---|---|
| 1.x | v1 | Supported |
| 2.x (planned Phase 2) | v1 + v2 | Overlap window 90 d during migration |
5.2 Rollout coordination
When the BFF ships a breaking change to /bff/backoffice/v1/*, we:
- Ship
/bff/backoffice/v2/*first; keep v1 unchanged. - Release a desktop version that supports both.
- Wait for ≥ 95% of devices to be on the new desktop version (tracked via heartbeat
appVersion). - Raise the v1 deprecation Sunset header.
- Remove v1 after the deprecation window.
The app-version-floor mechanism allows us to force devices off truly broken versions; it is reserved for emergencies (e.g., known data-corruption bug).
6. CI/CD pipeline
GitHub PR → GitHub Actions
├── Lint + typecheck + unit + integration + contract tests
├── Build container (Cloud Build)
├── Trivy scan
├── Cosign sign
├── Push to Artifact Registry
├── Deploy to dev Cloud Run (no-traffic + smoke)
├── Manual approval → stage
└── Manual approval → prod (canary 10% → 50% → 100% over 30 min, with metric guardrails)
Binary authorization on prod cluster requires Cosign signature.
7. Traffic management
- Default routing: anycast → nearest healthy region.
- Canary control via Cloud Deploy + Cloud Run revisions.
- Rollback budget 5 minutes if SLO burn detected.
- Force-logout broadcasts cross-region via Pub/Sub fanout to all instances; SSE bus locally fanned out per device.
8. Configuration
| Source | What |
|---|---|
| Cloud Run env vars | Non-secret toggles |
| Secret Manager (file mounts) | Secrets |
| Cloud Run Service YAML | Sizing, scaling, VPC connector |
bff-backoffice-flags (Memorystore) | Feature flags + sample rates + app-version floor (30 s refresh) |
9. Networking
- VPC:
melmastoon-prod-vpc. - Subnet for Cloud Run connector:
bff-backoffice-connector-asia-south1(10.20.7.0/28). - Private Service Access for Cloud SQL.
- Memorystore via VPC connector private IP.
10. Cost posture
| Item | Estimated monthly @ 50 RPS steady |
|---|---|
| Cloud Run | ~$220 |
| Memorystore (cache 5 GiB + session 3 GiB) | ~$280 |
| Cloud SQL (db-custom-2-8192 + HA) | ~$240 |
| Pub/Sub | ~$40 |
| Cloud Armor | ~$30 |
| Logging + Trace + Monitoring | ~$80 |
| Total | ~$890 / month / region |
11. Disaster recovery
- RPO: 5 min (Cloud SQL PITR).
- RTO: 30 min (DNS + redeploy in DR).
- Quarterly DR drill: cut traffic to
europe-west4; verify desktop fleet reconnects via DNS. - Sessions in Memorystore are best-effort — session loss in DR scenario triggers a
/auth/refreshfrom the desktop; idempotency keys absorb mutation retries.
12. Health endpoints
/health/live: 200 if process running./health/ready: 200 if Memorystore + Postgres + 80% upstream circuits closed.
Cloud Run liveness + readiness probes pointed at these.
13. Capacity model
| Driver | Per-tenant peak | All-tenant peak (50 tenants) |
|---|---|---|
| Active operators | 30 | 1,500 |
| Active devices | 50 | 2,500 |
| Heartbeats | 50/min | 2,500/min |
| Dashboard reads | 30/min | 1,500/min |
| Mutations | 60/min | 3,000/min |
| Lock actions | 10/hour | 500/hour |
| AI decisions | 5/hour | 250/hour |
| SSE connections | 50 | 2,500 |
14. Observability of deploy
- Cloud Build job emits OpenTelemetry traces.
- Deploy event published to
melmastoon.platform.deployment.v1(consumed by SRE dashboards). - Per-revision RED metrics tagged with
bff_versionallow rollback evaluation.
15. Operational notes
- Heartbeat traffic is high-volume + low-value; sample 5%; do not page on heartbeat alerts unless SLO-relevant.
- SSE long-running connections matter for instance recycling; pre-stop hook drains SSE gracefully (sends
event: session\ndata: {"kind":"reconnect"}then closes). - Per-device idempotency state on Postgres: cleanup hourly; daily archival.
- App-version floor change is a breaking operational action; requires runbook execution + Slack announcement.
16. Cross-references
- SYNC_CONTRACT — Electron sync handshake protocol
- SECURITY_MODEL — Container hardening, DPoP, MFA
- DATA_MODEL — Postgres + Memorystore sizing
- 02 Enterprise Architecture · §4 GCP Reference Architecture
- ADR-0003