Skip to main content

Environment Configuration

Manage deployment environments across the Olympus Cloud platform.

Overview

Olympus Cloud uses three primary environments:

EnvironmentPurposeDomainGCP Project
DevelopmentDevelopment and testing*.dev.olympuscloud.aiolympuscloud-dev
StagingPre-production validation*.staging.olympuscloud.aiolympuscloud-staging
ProductionLive customer traffic*.olympuscloud.aiolympuscloud-prod

Environment Hierarchy

┌─────────────────────────────────────────────────────────────────┐
│ Production │
│ • Real customer data • Full redundancy │
│ • High availability • Strict change control │
├─────────────────────────────────────────────────────────────────┤
│ Staging │
│ • Production-like config • Integration testing │
│ • Synthetic data • Performance testing │
├─────────────────────────────────────────────────────────────────┤
│ Development │
│ • Rapid iteration • Unit testing │
│ • Feature branches • GCP dev project │
└─────────────────────────────────────────────────────────────────┘

Configuration Files

Terraform Variables

# environments/dev/terraform.tfvars
project_id = "olympuscloud-dev"
environment = "dev"
region = "us-central1"

# Compute
cloud_run_min_instances = 0
cloud_run_max_instances = 10

# Database
spanner_instance_config = "regional-us-central1"
spanner_processing_units = 100

# Networking
enable_private_networking = false
# environments/staging/terraform.tfvars
project_id = "olympuscloud-staging"
environment = "staging"
region = "us-central1"

cloud_run_min_instances = 1
cloud_run_max_instances = 20

spanner_instance_config = "regional-us-central1"
spanner_processing_units = 500

enable_private_networking = true
# environments/prod/terraform.tfvars
project_id = "olympuscloud-prod"
environment = "prod"
region = "us-central1"

cloud_run_min_instances = 2
cloud_run_max_instances = 100

spanner_instance_config = "nam3" # Multi-region
spanner_processing_units = 2000

enable_private_networking = true

Application Configuration

# config/environments/development.yaml
environment: development
log_level: debug

database:
instance: dev-olympus-spanner
database: olympus-db
pool_size: 10

cache:
host: ${REDIS_HOST} # Memorystore private IP
port: 6378
tls: true

features:
debug_mode: true
mock_payments: true
seed_data: true
# config/environments/production.yaml
environment: production
log_level: info

database:
instance: prod-olympus-spanner
database: olympus-db
pool_size: 50

cache:
host: redis.olympuscloud.internal
port: 6379
tls: true
# TLS Note: Memorystore uses a private CA. All services skip CA
# verification while keeping encryption active. See below.

features:
debug_mode: false
mock_payments: false
seed_data: false
Redis / Memorystore TLS

Google Cloud Memorystore uses a private self-signed CA not in any public trust store. All services automatically skip CA verification while keeping TLS encryption active. This is safe because connections travel over private VPC within Google's network.

  • Rust: Uses #insecure URL fragment (tls-rustls-insecure feature)
  • Go: Sets TLSConfig.InsecureSkipVerify = true for rediss:// URLs
  • Python: Sets ssl_cert_reqs = ssl.CERT_NONE for rediss:// URLs

No REDIS_CA_CERT environment variable is needed. Connection strings use rediss:// protocol (note the double s) to enable TLS.


Secrets Management

Google Secret Manager

# Create secret
echo -n "secret-value" | gcloud secrets create api-key \
--project olympuscloud-prod \
--data-file=-

# Add version
echo -n "new-secret-value" | gcloud secrets versions add api-key \
--project olympuscloud-prod \
--data-file=-

# Access secret
gcloud secrets versions access latest \
--secret api-key \
--project olympuscloud-prod

Secret Structure

projects/olympuscloud-prod/secrets/
├── database-password
├── jwt-signing-key
├── stripe-api-key
├── stripe-webhook-secret
├── sendgrid-api-key
├── cloudflare-api-token
├── sentry-dsn
└── encryption-master-key

Environment-Specific Secrets

# Development
gcloud secrets create stripe-api-key-dev \
--project olympuscloud-dev

# Staging
gcloud secrets create stripe-api-key-staging \
--project olympuscloud-staging

# Production
gcloud secrets create stripe-api-key-prod \
--project olympuscloud-prod

Application Access

// src/config.rs
use google_cloud_secretmanager::client::SecretManagerServiceClient;

pub async fn load_secret(name: &str) -> Result<String> {
let client = SecretManagerServiceClient::new().await?;

let secret_name = format!(
"projects/{}/secrets/{}/versions/latest",
std::env::var("GCP_PROJECT")?,
name
);

let response = client.access_secret_version(&secret_name).await?;
let payload = response.payload.ok_or(Error::NoPayload)?;

String::from_utf8(payload.data)
.map_err(|e| Error::InvalidSecret(e.to_string()))
}

Feature Flags

Configuration

# config/feature_flags.yaml
flags:
voice_ordering:
description: "Enable voice AI ordering"
default: false
environments:
development: true
staging: true
production: false

new_checkout:
description: "New checkout flow"
default: false
rollout:
staging: 100
production: 10 # 10% rollout

ai_recommendations:
description: "AI-powered menu recommendations"
default: true
tenant_overrides:
- tenant_id: "enterprise-customer"
enabled: true

Implementation

// src/features.rs
pub struct FeatureFlags {
config: FeatureConfig,
environment: Environment,
}

impl FeatureFlags {
pub fn is_enabled(&self, flag: &str, ctx: &RequestContext) -> bool {
let flag_config = match self.config.flags.get(flag) {
Some(f) => f,
None => return false,
};

// Check tenant override
if let Some(overrides) = &flag_config.tenant_overrides {
if let Some(override_) = overrides.iter()
.find(|o| o.tenant_id == ctx.tenant_id)
{
return override_.enabled;
}
}

// Check environment setting
if let Some(env_setting) = flag_config.environments.get(&self.environment) {
return *env_setting;
}

// Check rollout percentage
if let Some(rollout) = flag_config.rollout.get(&self.environment) {
let hash = hash_user(&ctx.user_id);
return (hash % 100) < *rollout;
}

flag_config.default
}
}

Database Configuration

All environments use live Cloud Spanner instances in GCP. There is no local emulator.

Cloud Spanner Instances

EnvironmentGCP ProjectInstance NameDatabase
Devolympuscloud-devdev-olympus-spannerolympus-db
Stagingolympuscloud-stagingstaging-olympus-spannerolympus-db
Prodolympuscloud-prodprod-olympus-spannerolympus-db

Terraform Configuration

# Cloud Spanner configuration (all environments)
resource "google_spanner_instance" "olympus" {
name = "${var.environment}-olympus-spanner"
config = var.spanner_instance_config
display_name = "Olympus ${title(var.environment)}"

processing_units = var.spanner_processing_units

labels = {
environment = var.environment
}
}

resource "google_spanner_database" "olympus" {
instance = google_spanner_instance.olympus.name
name = "olympus-db"

deletion_protection = var.environment == "prod"

ddl = [
file("${path.module}/schema/tenants.sql"),
file("${path.module}/schema/locations.sql"),
file("${path.module}/schema/orders.sql"),
]
}

Network Configuration

All environments use Cloud Run with VPC connectors. There is no Docker/localhost networking.

VPC Configuration

# VPC configuration
resource "google_compute_network" "olympus" {
name = "olympus-${var.environment}"
auto_create_subnetworks = false
}

resource "google_compute_subnetwork" "services" {
name = "services-${var.environment}"
ip_cidr_range = "10.0.0.0/20"
network = google_compute_network.olympus.id
region = var.region

private_ip_google_access = true
}

# VPC Connector for Cloud Run
resource "google_vpc_access_connector" "connector" {
name = "olympus-connector-${var.environment}"
region = var.region
ip_cidr_range = "10.8.0.0/28"
network = google_compute_network.olympus.name
}

Deployment Workflow

Development

# Run tests
make test

# Deploy to dev environment
make deploy-dev

Staging

# Deploy to staging (automatic on PR merge to develop)
git push origin develop

# Manual staging deployment
make deploy-staging

Production

danger

Production deployments require explicit approval. Never bypass the staging validation step. All changes must pass quality gates in staging before promotion to production. Running make deploy-prod without CONFIRM=yes is a safety check -- do not script around it.

# Production deployment (requires approval)
git push origin main

# Manual production deployment
make deploy-prod CONFIRM=yes

Promotion Flow

Feature Branch


develop (auto-deploy to dev)


staging (auto-deploy on merge)


main (deploy with approval)


Production

Environment Variables

Required Variables

VariableDevStagingProdDescription
ENVIRONMENTdevelopmentstagingproductionCurrent environment
GCP_PROJECTolympuscloud-devolympuscloud-stagingolympuscloud-prodGCP project
LOG_LEVELdebuginfoinfoLogging verbosity
SPANNER_INSTANCEdev-olympus-spannerstaging-olympus-spannerprod-olympus-spannerDatabase instance

Service URLs

VariableDevStagingProd
API_GATEWAY_URLhttps://dev.api.olympuscloud.ai/api/v1https://staging.api.olympuscloud.ai/api/v1https://api.olympuscloud.ai/api/v1
PLATFORM_SERVICE_URLInternal Cloud Run URLInternal Cloud Run URLInternal Cloud Run URL
COMMERCE_SERVICE_URLInternal Cloud Run URLInternal Cloud Run URLInternal Cloud Run URL

Monitoring by Environment

Alert Thresholds

MetricDevStagingProd
Error rateNone> 5%> 1%
Latency (p99)None> 1s> 500ms
CPU utilizationNone> 90%> 80%
Memory utilizationNone> 90%> 85%

Log Retention

EnvironmentRetentionArchive
Development7 daysNone
Staging30 daysNone
Production90 days7 years (compliance)

Troubleshooting

Environment Mismatch

# Verify current environment
echo $ENVIRONMENT

# Check GCP project
gcloud config get-value project

# Verify service configuration
gcloud run services describe platform-service \
--format "value(spec.template.spec.containers[0].env)"

Connection Issues

# Test database connectivity
# Instance names: dev-olympus-spanner, staging-olympus-spanner, prod-olympus-spanner
gcloud spanner databases execute-sql olympus-db \
--instance ${ENVIRONMENT}-olympus-spanner \
--sql "SELECT 1"

# Test service connectivity
curl -v https://${ENVIRONMENT}.api.olympuscloud.ai/health