GCP Project Consolidation — HubOps / Deliveries
| Status | Draft |
| Classification | INTERNAL |
| Scope | droneup-deliveries, droneup-deliveries-dev, droneup-hubops-dev, droneup-hubops-prod, mongodb-hubops-service |
| Date | 2026-03-30 |
| Source | Automated analysis via repository code search, cross-checked against local copies of droneup-hubops-infrastructure, hubops-mission-service, hubops-delivery-react-native, and pe-tfc-automation |
Executive Summary
The HubOps / Delivery platform is spread across five GCP projects because the migration from the original “Deliveries” projects to the newer “HubOps” projects was never completed. Today:
- Firestore + Firebase Auth remain in the legacy
droneup-deliveries/droneup-deliveries-devprojects. - Compute (GKE), PubSub, Secret Manager, CloudSQL, Redis run in
droneup-hubops-dev/droneup-hubops-prod. mongodb-hubops-serviceis a standalone project with no active code references — a likely abandoned MongoDB Atlas peering project.- Every HubOps microservice carries cross-project IAM bindings so it can reach the legacy Firestore, adding operational and cost overhead.
Recommendation: consolidate the five projects into two (droneup-hubops-dev and droneup-hubops-prod) through a phased migration. Delete mongodb-hubops-service immediately.
content/docs/HubOps/ADR/ once the platform team agrees on the target state and migration ownership.1. Current State
1.1 Project Inventory
| GCP Project | Status | Active Resources | Recommendation |
|---|---|---|---|
droneup-deliveries | Legacy | Firestore, Cloud Functions, GCS, PubSub, Firebase Auth | Migrate to droneup-hubops-prod, then delete |
droneup-deliveries-dev | Legacy | Firestore, Cloud Functions, GCS, PubSub | Migrate to droneup-hubops-dev, then delete |
droneup-hubops-dev | Active | GKE, CloudSQL, PubSub, GSM, Redis | Keep — absorb droneup-deliveries-dev resources |
droneup-hubops-prod | Active | GKE, CloudSQL, PubSub, GSM, Redis | Keep — absorb droneup-deliveries resources |
mongodb-hubops-service | Abandoned | None found | Delete immediately |
1.2 Dependency Map
graph TB
subgraph compute["Primary Compute (HubOps)"]
HP["droneup-hubops-prod<br/>GKE • PubSub • GSM<br/>CloudSQL • Redis"]
HD["droneup-hubops-dev<br/>GKE • PubSub • GSM<br/>CloudSQL • Redis"]
end
subgraph legacy["Legacy Firestore / Firebase"]
DP["droneup-deliveries<br/>Firestore • Cloud Functions<br/>GCS • PubSub • Firebase Auth"]
DD["droneup-deliveries-dev<br/>Firestore • Cloud Functions<br/>GCS • PubSub"]
end
HP -- "Firestore reads<br/>(cross-project IAM)" --> DP
HD -- "Firestore reads<br/>(cross-project IAM)" --> DD
MH["mongodb-hubops-service<br/>NO ACTIVE USE"]
2. Project-by-Project Breakdown
droneup-deliveries (prod — legacy Firestore/Firebase)
| Resource Type | Details |
|---|---|
| Firestore DB | Primary production Firestore — used by nearly all HubOps prod services |
| Cloud Functions | deliveries-live-function (invoked via PubSub and from the mobile app) |
| GCS Buckets | droneup-deliveries-fsb (Firestore backup), deliveries-live-sf-data |
| PubSub Topics | email-notifications, sms-notifications, hub-active, suspensions, deliveries-live-store0001, deliveries-test-store0000 |
| Firebase Auth | Used by hubops-delivery-react-native mobile app |
Services depending on this project (prod Firestore):
| Repository | How it uses droneup-deliveries |
|---|---|
hubops-mission-service | FIREBASE_PROJECT_ID: "droneup-deliveries" (verified in values-prod.yml:24) |
hubops-mission-planner | FIREBASE_PROJECT_ID: "droneup-deliveries" |
hubops-walmart-deliveries-service | FIRESTORE_PROJECT_ID: "droneup-deliveries-prod" ¹ |
hubops-firestore-api | FIRESTORE_PROJECT_ID: "droneup-deliveries-prod" ¹ |
hubops-order-service | FIREBASE_PROJECT_ID: "droneup-deliveries" |
hubops-reservation-service | FIREBASE_PROJECT_ID: "droneup-deliveries" |
hubops-weather-cache | FIREBASE_PROJECT_ID: "droneup-deliveries" |
hubops-bucket-populator | FIRESTORE_PROJECT_ID + FIREBASE_PROJECT_ID = droneup-deliveries |
hubops-delivery-api-v2 | FIRESTORE_PROJECT_ID: "droneup-deliveries" |
acs-bucket-populator | FIRESTORE_PROJECT_ID: droneup-deliveries |
hubops-delivery-react-native | Firebase Auth + cloudfunctions.net/deliveries-activeUser (verified in src/api/auth/auth.api.ts:13-16) |
da-composer-pipelines | SRC_PROJECT_ID = 'droneup-deliveries' (Airflow DAG: Firestore → BigQuery) |
terraform-google-flightops | PubSub integration with deliveries-live-function |
terraform-google-pubsub-hubops | PubSub module referencing deliveries_project_name |
¹ Some services use droneup-deliveries-prod as a string alias — this either resolves to droneup-deliveries or reflects inconsistent naming. Reconcile during Phase 1.
Cross-project IAM bindings into droneup-deliveries (from pe-gcp-service-accounts):
acs-delivery-api-prod@droneup-hubops-prod→roles/datastore.useracs-bucket-populator@droneup-hubops-prod→roles/datastore.viewerhubops-api@droneup-hubops-prod→roles/datastore.user,roles/storage.objectAdmin,ServiceAccountPubSubhubops-weather-cache-svc-acc@droneup-hubops-prod→roles/datastore.userhubops-wm-deliveries@droneup-hubops-prod→roles/datastore.viewerhubops-firebase-svc-account@droneup-hubops-prod→roles/datastore.userhubops-mission-service@droneup-hubops-prod→roles/datastore.userhubops-gcp-functions@droneup-hubops-prod→roles/datastore.user,ServiceAccountPubSubterraform-cloud@droneup-hubops-prod→roles/admin
droneup-deliveries-dev (dev — legacy Firestore/Firebase)
| Resource Type | Details |
|---|---|
| Firestore DB | Dev / sandbox Firestore — used by all HubOps dev and sandbox services |
| Cloud Functions | deliveries-dev-function |
| GCS Buckets | droneup-deliveries-dev-fsb (Firestore backup) |
| PubSub Topics | deliveries-dev-store0001, email-notifications, sms-notifications, hub-active, suspensions |
Services depending on this project (dev Firestore):
| Repository | How it uses droneup-deliveries-dev |
|---|---|
hubops-mission-service | FIREBASE_PROJECT_ID: "droneup-deliveries-dev" (verified in values-dev.yml:24, values-sandbox.yml:29) |
hubops-mission-planner | FIREBASE_PROJECT_ID: "droneup-deliveries-dev" |
hubops-firestore-api | FIRESTORE_PROJECT_ID: "droneup-deliveries-dev" (dev + sandbox) |
hubops-order-service | FIREBASE_PROJECT_ID: "droneup-deliveries-dev" (dev + sandbox) |
hubops-reservation-service | FIREBASE_PROJECT_ID: "droneup-deliveries-dev" (dev + sandbox) |
hubops-weather-cache | FIREBASE_PROJECT_ID: "droneup-deliveries-dev" (sandbox) |
hubops-bucket-populator | FIRESTORE_PROJECT_ID + FIREBASE_PROJECT_ID = droneup-deliveries-dev |
hubops-delivery-api-v2 | FIRESTORE_PROJECT_ID: "droneup-deliveries-dev" (dev + sandbox) |
hubops-systems-check | Hardcoded ProjectID: "droneup-deliveries-dev" in Go source |
hubops-gcp-functions | Firebase emulator configured with --project droneup-deliveries-dev |
hubops-delivery-react-native | Auth URL routing keyed on projectId === 'droneup-deliveries-dev' (verified in src/store/auth/actions.ts:21, src/api/orders/orders.api.ts:50) |
acs-bucket-populator | FIRESTORE_PROJECT_ID: droneup-deliveries-dev (sandbox) |
acs-local-compose | FIRESTORE_PROJECT_ID=droneup-deliveries-dev |
Cross-project IAM bindings into droneup-deliveries-dev:
acs-delivery-api-dev@droneup-hubops-dev→roles/datastore.useracs-bucket-populator-dev@droneup-hubops-dev→roles/datastore.viewerhubops-api-dev@droneup-hubops-dev→roles/datastore.user,roles/storage.objectAdmin,ServiceAccountPubSubhubops-weather-cache-svc-acc@droneup-hubops-dev→roles/datastore.userterraform-cloud@droneup-hubops-dev→roles/admin- Several SAs in
droneup-deliveries-devitself:hubops-dbupdate,hubops-auth-service,hubops-publicapi-deliveries,location-availability-service
droneup-hubops-dev (primary compute — dev)
| Resource Type | Details |
|---|---|
| GKE Cluster | droneup-hubops-dev (us-east1) |
| CloudSQL | PostgreSQL instances for control-plane, walmart-deliveries, GIS backend, etc. |
| PubSub | All dev/sandbox topics (missions, orders, control-plane, status updates, weather cache) |
| Secret Manager | All dev/sandbox secrets for HubOps services |
| Redis | Memorystore (172.19.0.12:6379) |
| Shared VPC Subnet | droneup-hubops-dev-gke-subnet (in droneup-shared-prod) |
| Cloudflare Tunnel | Zero-trust access configured |
Services deployed to this GKE cluster (dev / sandbox): hubops-mission-service, hubops-mission-planner, hubops-walmart-deliveries-service, hubops-firestore-api, hubops-order-service, hubops-reservation-service, hubops-weather-cache, hubops-bucket-populator, hubops-delivery-api-v2, hubops-control-plane, hubops-status-manager, hubops-systems-check, hubops-gcp-functions, groundinfrasvc-backend.
droneup-hubops-prod (primary compute — prod)
| Resource Type | Details |
|---|---|
| GKE Cluster | droneup-hubops-prod (us-east1) |
| CloudSQL | hubops-cloudsql-prod, hubops-faa-prod, hubops-controlplane-prod (verified in droneup-hubops-infrastructure/main.tf) — all created under var.project_name for the prod project |
| PubSub | All prod topics |
| Secret Manager | All prod secrets |
| Redis | Memorystore (172.18.0.20:6379) |
| Shared VPC Subnet | droneup-hubops-prod-gke-subnet |
| Cloudflare Tunnel | Zero-trust access configured |
| Artifact Registry | Service accounts have reader access into pe-tools-main |
Warning
The original analysis flagged a suspicious DB_HOST: "droneup-hubops-dev:us-east1:hubops-cloudsql-prod-f5326ae7" value in hubops-walmart-deliveries-service prod config, suggesting the prod CloudSQL instance might physically reside in the dev project. A terraform review of droneup-hubops-infrastructure did not find an instance named hubops-cloudsql-prod-f5326ae7; actual prod instances (hubops-cloudsql-prod, hubops-faa-prod, hubops-controlplane-prod) are created under the prod project. The helm value is likely stale and should be reconciled as part of Phase 0 before migration begins.
Services deployed (prod): same list as dev, in the services namespace.
mongodb-hubops-service
| Finding | Details |
|---|---|
| Code references | Found only in pe-gcp-service-accounts/modules/prod/main.tf as part of a bulk org-wide project list |
| Active services | None found |
| Terraform management | Listed alongside other legacy / abandoned projects |
| Likely purpose | Probably created for a MongoDB Atlas ↔ GCP peering for HubOps that never shipped |
Conclusion: abandoned — delete immediately after a GCP console sanity check.
3. Recommendations
Phase 0 — Quick Wins Immediate
| # | Action | Effort | Savings / Benefit |
|---|---|---|---|
| 1 | Delete mongodb-hubops-service after confirming GCP console shows no resources | Low | Eliminates billing for an idle project |
| 2 | Clean up legacy PubSub topics in droneup-deliveries / -dev with no live subscribers (e.g. deliveries-test-store0000) | Low | Minor cost + hygiene |
| 3 | Verify the DB_HOST in hubops-walmart-deliveries-service prod config — reconcile against actual CloudSQL instances found in droneup-hubops-infrastructure | Low (investigation) | Removes risk of prod pointing at a ghost instance |
Phase 1 — Consolidate Deliveries into HubOps Medium-term
The core problem: Firestore stayed in the old droneup-deliveries* projects while everything else moved to droneup-hubops*. The migration was never finished.
| # | Action | Details |
|---|---|---|
| 4 | Migrate Firestore data droneup-deliveries → droneup-hubops-prod and droneup-deliveries-dev → droneup-hubops-dev | gcloud firestore export / import. Every consumer already reads FIREBASE_PROJECT_ID / FIRESTORE_PROJECT_ID from env, so the cutover is a values-file change + redeploy. |
| 5 | Migrate Cloud Functions (deliveries-live-function, deliveries-dev-function) to Cloud Run in the hubops projects, or rewrite as GKE services | The mobile app calls cloudfunctions.net/deliveries-activeUser — will need a URL update (or a redirect proxy in the interim). |
| 6 | Complete Firebase Auth → Frontegg migration (already partially done) | Some services reference both auth0 and Frontegg. Finish the migration so Firebase Auth can be retired. |
| 7 | Move GCS buckets (droneup-deliveries-fsb, droneup-deliveries-dev-fsb) to hubops projects | gsutil or Storage Transfer Service |
| 8 | Update all service configs — FIREBASE_PROJECT_ID / FIRESTORE_PROJECT_ID env vars across ~15 repositories | Bulk of the work. Coordinate with deployment windows. |
| 9 | Update da-composer-pipelines — the Airflow DAG (composer/dags/hubops/hubops.py) exports from SRC_PROJECT_ID = 'droneup-deliveries' | Must change in sync with cutover |
| 10 | Remove cross-project IAM bindings in pe-gcp-service-accounts and legacy TFC workspaces (du-deliveries, du-deliveries-dev — verified in pe-tfc-automation/legacy_tfc.tf) | Clean up after migration, before project deletion |
Exit criterion: both droneup-deliveries and droneup-deliveries-dev can be deleted with no active references.
Phase 2 — Target State (2 projects) Final
graph TB
subgraph target["Target: 2 GCP projects"]
direction LR
HP["droneup-hubops-prod<br/>GKE • Firestore • Firebase Auth<br/>PubSub • GSM • CloudSQL<br/>Redis • GCS"]
HD["droneup-hubops-dev<br/>GKE • Firestore • Firebase Auth<br/>PubSub • GSM • CloudSQL<br/>Redis • GCS"]
end
subgraph deleted["Deleted"]
DD["droneup-deliveries"]
DE["droneup-deliveries-dev"]
MH["mongodb-hubops-service"]
end
style deleted fill:#fee,stroke:#c33,stroke-dasharray:5
Estimated cost reduction from eliminating three GCP projects:
- Three sets of project-level charges (logging, monitoring)
- Cross-project network egress (Firestore reads from hubops → deliveries)
- Unused Cloud Functions billing
- Unused GCS storage for legacy backups
- IAM surface area — fewer service accounts to rotate and audit
4. Repositories Affected
Phase 0
None — GCP Console and Terraform operations only.
Phase 1 — config + Terraform changes
| Repository | Change Needed |
|---|---|
hubops-mission-service | Update FIREBASE_PROJECT_ID in values-dev.yml, values-sandbox.yml, values-prod.yml |
hubops-mission-planner | Update FIREBASE_PROJECT_ID in values-dev.yml, values-prod.yml |
hubops-walmart-deliveries-service | Update FIRESTORE_PROJECT_ID in values-prod.yml (and reconcile DB_HOST per Phase 0 #3) |
hubops-firestore-api | Update FIRESTORE_PROJECT_ID in all values-*.yml |
hubops-order-service | Update FIREBASE_PROJECT_ID in all values-*.yml |
hubops-reservation-service | Update FIREBASE_PROJECT_ID in all values-*.yml |
hubops-weather-cache | Update FIREBASE_PROJECT_ID in all values-*.yml |
hubops-bucket-populator | Update FIRESTORE_PROJECT_ID + FIREBASE_PROJECT_ID in all values-*.yml |
hubops-delivery-api-v2 | Update FIRESTORE_PROJECT_ID in all values-*.yml |
hubops-systems-check | Code change — hardcoded ProjectID: "droneup-deliveries-dev" in internal/database/firestore.go |
hubops-gcp-functions | Update Firebase emulator --project flag in Makefile |
hubops-delivery-react-native | Code change — droneup-deliveries fallback in src/api/auth/auth.api.ts:13; deliveries-activeUser URL in src/api/auth/auth.api.ts:16; dev-vs-prod routing in src/store/auth/actions.ts, src/api/orders/orders.api.ts |
acs-bucket-populator | Update FIRESTORE_PROJECT_ID in all values-*.yml |
acs-local-compose | Update FIRESTORE_PROJECT_ID in podman-compose.yml |
da-composer-pipelines | Update SRC_PROJECT_ID in composer/dags/hubops/hubops.py |
pe-gcp-service-accounts | Remove all droneup-deliveries* service accounts and cross-project role bindings |
pe-gcp-iam | Remove droneup-deliveries / droneup-deliveries-dev from live_projects / dev_projects |
pe-tfc-automation | Remove du-deliveries / du-deliveries-dev workspace definitions in legacy_tfc.tf |
droneup-hubops-infrastructure | Remove legacy/droneup-deliveries* folders (including legacy-deliveries-service-accounts.tf) after migration completes |
pe-terraform-iasc | Archive droneup-deliveries folder |
terraform-google-flightops | Update function_project_name defaults |
terraform-google-pubsub-hubops | Update deliveries_project_name parameter |
5. Risks and Mitigations
| Risk | Mitigation |
|---|---|
| Firestore migration downtime | Use export/import in a maintenance window. Because all consumers read the project ID from env, the cutover is a coordinated redeploy, not a code change. |
| Firebase Auth user disruption | Firebase Auth users exist per-project. Plan explicit user migration or complete the move to Frontegg first (already in progress). |
| Mobile app update required | hubops-delivery-react-native hardcodes cloudfunctions.net URLs — requires an app-store release. Stand up a redirect/proxy to bridge the cutover while users update. |
| Data analytics pipeline breakage | da-composer-pipelines reads droneup-deliveries Firestore directly — must be updated in sync with the cutover. |
| Terraform state conflicts | Legacy TFC workspaces in pe-tfc-automation reference droneup-deliveries* — migrate or delete the states before deleting the projects. |
Stale DB_HOST in prod helm config | Reconcile before Phase 1 (see Phase 0 #3) so the walmart deliveries service is verifiably pointing at the correct CloudSQL instance. |
6. References
droneup-hubops-infrastructure/legacy/— verified legacy folder tree withdroneup-deliveries+droneup-deliveries-devsubdirspe-tfc-automation/legacy_tfc.tf— verifieddu-deliveries/du-deliveries-devworkspace definitionshubops-delivery-react-native/src/api/auth/auth.api.ts— verified hardcodeddroneup-deliveries+cloudfunctions.net/deliveries-activeUserreferenceshubops-mission-serviceHelm values — verifiedFIREBASE_PROJECT_IDsettings per environment
7. Next Steps
- Review with the HubOps platform team and name a migration owner.
- Execute Phase 0 this sprint (deletion of
mongodb-hubops-service, PubSub cleanup,DB_HOSTreconciliation). - Open an ADR under
content/docs/HubOps/ADR/capturing the consolidation decision once target state is agreed. - Plan Phase 1 as a multi-sprint initiative — migration runbook, Frontegg completion, mobile app release schedule, analytics pipeline cutover.