Skip to content

Environments Matrix

Side-by-side comparison of everything that differs between dev and prod. Anything not listed here is shared.

Kubernetes

Dev Prod
App namespace tomoda prod
Argo Application name tomoda prod-tomoda
Kustomize overlay path k8s/apps/tomoda/overlays/dev k8s/apps/tomoda/overlays/prod
Image-Updater strategy latest newest-build (semver tags)
Backend envFrom secret backend-secrets-dev backend-secrets-prod
Backend config ConfigMap backend-config-dev backend-config-prod
Backend GIN_MODE (default) release
imagePullPolicy patch (default) IfNotPresent
PodDisruptionBudget none tomoda-api-pdb + tomoda-async-pdb (both minAvailable: 50%)
HorizontalPodAutoscaler tomoda-api-hpa + tomoda-async-hpa (CPU 70 + mem 80; bounds 1-3) tomoda-api-hpa + tomoda-async-hpa (CPU 70 + mem 80; bounds 2-6)
Extra ingress host www.tomoda.life

Data plane

Dev Prod
CNPG Cluster name postgres-dev postgres-prod
DB name tomoda_dev tomoda_prod
DB owner tomoda_dev_user tomoda_prod_user
Credentials Secret postgres-dev-credentials (ESO) postgres-prod-credentials (ESO)
Storage size 10Gi 20Gi
shared_buffers 128MB 256MB
effective_cache_size (not set) 512MB
log_statement all none
log_min_duration_statement (not set) 1000 ms
CPU limit 500m 1000m
Memory limit 512Mi 1024Mi
Barman path gs://tomoda-db-backups-development-485000/dev/ gs://tomoda-db-backups-development-485000/prod/
ExternalName alias service postgres-postgresql prod-postgres-postgresql
Redis Helm release redis prod-redis
Redis persistence size 5Gi 10Gi
Redis metrics exporter enabled (ServiceMonitor) not enabled in values.yaml
Redis CPU limit 100m 1 (1 full core)
Redis memory limit 128Mi 1024Mi

Both Postgres clusters and both Redis releases live in the shared data namespace and are distinguished by name.

Ingress hosts

Purpose Dev Prod
API api-dev.tomoda.life api.tomoda.life
App app-dev.tomoda.life app.tomoda.life
Public marketing www.tomoda.life
Static assets assets-dev.tomoda.life assets.tomoda.life
WebSocket origin wss://api-dev.tomoda.life/ws wss://api.tomoda.life/ws
Frontend API base https://api-dev.tomoda.life/api/v1 https://api.tomoda.life/api/v1

The argo-app.tomoda.life ArgoCD UI is shared across environments (one cluster, one Argo CD).

Build and image pipeline

Dev Prod
Cloud Build trigger backend-push-trigger, frontend-push-trigger backend-release-trigger, frontend-release-trigger
Trigger source push to main (paths-filtered) tags matching ^v[0-9]+\.[0-9]+\.[0-9]+$
Approval Manual approval required Auto-approved
Artifact Registry repo tomoda-dev-repo (in asia-east1) tomoda-prod-repo (in asia-east1)
Tag policy latest (mutating) semver, immutable
Frontend Google web client ID 287267207777-... 693047704086-...

Both pipelines run from infrastructure/gcp/cloudbuild.tf using the same cloudbuild-backend.yaml / cloudbuild-frontend.yaml files in the tomoda app repo, parametrized by substitutions.

AWS / CDN

Dev Prod
Terraform workspace dev default
S3 bucket tomoda-assets-dev tomoda-assets-prod
CloudFront alias assets-dev.tomoda.life assets.tomoda.life
ACM cert SAN assets-dev.tomoda.life assets.tomoda.life

The CloudFront price_class and Origin Access Control configuration are identical between environments (see infrastructure/aws/cloudfront.tf).

Shared between environments

For clarity, these are intentionally not split:

  • The GKE cluster gke-tomoda and its node pools.
  • The VPC gke-tomoda-vpc and its subnets.
  • All system services in k8s/envs/dev/sys/ (Traefik, cert-manager, ESO, external-dns, oauth2-proxy, monitoring, loki) — prod uses the dev-deployed instances.
  • The Argo CD control plane (argo-app.tomoda.life).
  • The Photon geocoder Service and its GCS-backed index (<project>-photon-index).
  • The GCS backup bucket (tomoda-db-backups-development-485000) — separated by prefix, not by bucket.
  • All GCP Secret Manager secrets except those with explicit -dev / -prod suffixes.
  • Cloudflare zone, IAM bindings, and Workload Identity service accounts.