# ── REST API (neuron-rest) — Cloud Run ──────────────────────────────────────── # Stateless API layer. Validates JWTs from accounts service. # No database connection — reads user context from accounts service. # cpu_idle=false: always-hot, no cold-start latency for API calls. locals { api_labels = { "managed-by" = "terraform" "service" = "neuron-api" } } # ── Prod — us-central1 ──────────────────────────────────────────────────────── resource "google_cloud_run_v2_service" "api_us" { name = "api-prod-us" location = "us-central1" project = var.project_id ingress = "INGRESS_TRAFFIC_ALL" labels = local.api_labels template { service_account = google_service_account.api.email scaling { min_instance_count = 1 max_instance_count = 100 } containers { image = local.api_image resources { limits = { cpu = "2" memory = "1Gi" } cpu_idle = false } env { name = "ENV" value = "production" } env { name = "SERVER_PORT" value = "8080" } env { name = "ACCOUNTS_SERVICE_URL" value = "https://accounts.neurontechnologies.ai" } env { name = "JWT_SECRET" value_source { secret_key_ref { secret = google_secret_manager_secret.jwt_secret.secret_id version = "latest" } } } env { name = "LICENSE_ADMIN_TOKEN" value_source { secret_key_ref { secret = google_secret_manager_secret.license_admin_token.secret_id version = "latest" } } } ports { container_port = 8080 name = "http1" } startup_probe { http_get { path = "/actuator/health" port = 8080 } initial_delay_seconds = 2 timeout_seconds = 5 period_seconds = 5 failure_threshold = 6 } liveness_probe { http_get { path = "/actuator/health" port = 8080 } timeout_seconds = 5 period_seconds = 30 failure_threshold = 3 } } max_instance_request_concurrency = 1000 } traffic { type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST" percent = 100 } depends_on = [ google_project_iam_member.api_secret_accessor, google_secret_manager_secret_version.jwt_secret, ] } # ── Prod — europe-west1 ─────────────────────────────────────────────────────── resource "google_cloud_run_v2_service" "api_eu" { name = "api-prod-eu" location = "europe-west1" project = var.project_id ingress = "INGRESS_TRAFFIC_ALL" labels = local.api_labels template { service_account = google_service_account.api.email scaling { min_instance_count = 1 max_instance_count = 100 } containers { image = local.api_image resources { limits = { cpu = "2" memory = "1Gi" } cpu_idle = false } env { name = "ENV" value = "production" } env { name = "SERVER_PORT" value = "8080" } env { name = "ACCOUNTS_SERVICE_URL" value = "https://accounts.neurontechnologies.ai" } env { name = "JWT_SECRET" value_source { secret_key_ref { secret = google_secret_manager_secret.jwt_secret.secret_id version = "latest" } } } env { name = "LICENSE_ADMIN_TOKEN" value_source { secret_key_ref { secret = google_secret_manager_secret.license_admin_token.secret_id version = "latest" } } } ports { container_port = 8080 name = "http1" } startup_probe { http_get { path = "/actuator/health" port = 8080 } initial_delay_seconds = 2 timeout_seconds = 5 period_seconds = 5 failure_threshold = 6 } liveness_probe { http_get { path = "/actuator/health" port = 8080 } timeout_seconds = 5 period_seconds = 30 failure_threshold = 3 } } max_instance_request_concurrency = 1000 } traffic { type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST" percent = 100 } depends_on = [google_project_iam_member.api_secret_accessor] } # ── Prod — asia-northeast1 ──────────────────────────────────────────────────── resource "google_cloud_run_v2_service" "api_apac" { name = "api-prod-apac" location = "asia-northeast1" project = var.project_id ingress = "INGRESS_TRAFFIC_ALL" labels = local.api_labels template { service_account = google_service_account.api.email scaling { min_instance_count = 1 max_instance_count = 100 } containers { image = local.api_image resources { limits = { cpu = "2" memory = "1Gi" } cpu_idle = false } env { name = "ENV" value = "production" } env { name = "SERVER_PORT" value = "8080" } env { name = "ACCOUNTS_SERVICE_URL" value = "https://accounts.neurontechnologies.ai" } env { name = "JWT_SECRET" value_source { secret_key_ref { secret = google_secret_manager_secret.jwt_secret.secret_id version = "latest" } } } env { name = "LICENSE_ADMIN_TOKEN" value_source { secret_key_ref { secret = google_secret_manager_secret.license_admin_token.secret_id version = "latest" } } } ports { container_port = 8080 name = "http1" } startup_probe { http_get { path = "/actuator/health" port = 8080 } initial_delay_seconds = 2 timeout_seconds = 5 period_seconds = 5 failure_threshold = 6 } liveness_probe { http_get { path = "/actuator/health" port = 8080 } timeout_seconds = 5 period_seconds = 30 failure_threshold = 3 } } max_instance_request_concurrency = 1000 } traffic { type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST" percent = 100 } depends_on = [google_project_iam_member.api_secret_accessor] }