From 1f94c16d4f4f210b1a21b0fecdbcb61b19b22829 Mon Sep 17 00:00:00 2001 From: Jakub Dobry Date: Mon, 9 Mar 2026 22:08:56 +0000 Subject: [PATCH 1/4] feat(api): make DB connection pool size configurable via env vars The main SQLC database pool had hardcoded max connections (40) and min idle (5). This adds DB_MAX_OPEN_CONNECTIONS and DB_MIN_IDLE_CONNECTIONS env vars, propagated through the Terraform -> Nomad pipeline, so pool sizes can be tuned per environment without code changes. --- iac/modules/job-api/jobs/api.hcl | 2 ++ iac/modules/job-api/main.tf | 2 ++ iac/modules/job-api/variables.tf | 10 ++++++++++ packages/api/internal/cfg/model.go | 2 ++ packages/api/internal/handlers/store.go | 2 +- 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/iac/modules/job-api/jobs/api.hcl b/iac/modules/job-api/jobs/api.hcl index 36ac73a1c0..47890160f1 100644 --- a/iac/modules/job-api/jobs/api.hcl +++ b/iac/modules/job-api/jobs/api.hcl @@ -119,6 +119,8 @@ job "api" { SANDBOX_ACCESS_TOKEN_HASH_SEED = "${sandbox_access_token_hash_seed}" POSTGRES_CONNECTION_STRING = "${postgres_connection_string}" + DB_MAX_OPEN_CONNECTIONS = "${db_max_open_connections}" + DB_MIN_IDLE_CONNECTIONS = "${db_min_idle_connections}" AUTH_DB_CONNECTION_STRING = "${postgres_connection_string}" AUTH_DB_READ_REPLICA_CONNECTION_STRING = "${postgres_read_replica_connection_string}" SUPABASE_JWT_SECRETS = "${supabase_jwt_secrets}" diff --git a/iac/modules/job-api/main.tf b/iac/modules/job-api/main.tf index 67e47ba6da..fcc8e0d8f0 100644 --- a/iac/modules/job-api/main.tf +++ b/iac/modules/job-api/main.tf @@ -28,6 +28,8 @@ resource "nomad_job" "api" { redis_url = var.redis_url redis_cluster_url = var.redis_cluster_url redis_tls_ca_base64 = var.redis_tls_ca_base64 + db_max_open_connections = var.db_max_open_connections + db_min_idle_connections = var.db_min_idle_connections redis_pool_size = var.redis_pool_size clickhouse_connection_string = var.clickhouse_connection_string loki_url = var.loki_url diff --git a/iac/modules/job-api/variables.tf b/iac/modules/job-api/variables.tf index 869e13fe97..4d66e43cf0 100644 --- a/iac/modules/job-api/variables.tf +++ b/iac/modules/job-api/variables.tf @@ -125,6 +125,16 @@ variable "redis_tls_ca_base64" { sensitive = true } +variable "db_max_open_connections" { + type = number + default = 40 +} + +variable "db_min_idle_connections" { + type = number + default = 5 +} + variable "redis_pool_size" { type = number default = 160 diff --git a/packages/api/internal/cfg/model.go b/packages/api/internal/cfg/model.go index c5779de472..7d96729884 100644 --- a/packages/api/internal/cfg/model.go +++ b/packages/api/internal/cfg/model.go @@ -38,6 +38,8 @@ type Config struct { NomadToken string `env:"NOMAD_TOKEN"` PostgresConnectionString string `env:"POSTGRES_CONNECTION_STRING,required,notEmpty"` + DBMaxOpenConnections int32 `env:"DB_MAX_OPEN_CONNECTIONS" envDefault:"40"` + DBMinIdleConnections int32 `env:"DB_MIN_IDLE_CONNECTIONS" envDefault:"5"` AuthDBConnectionString string `env:"AUTH_DB_CONNECTION_STRING"` AuthDBReadReplicaConnectionString string `env:"AUTH_DB_READ_REPLICA_CONNECTION_STRING"` diff --git a/packages/api/internal/handlers/store.go b/packages/api/internal/handlers/store.go index 56bf28631b..d5741905df 100644 --- a/packages/api/internal/handlers/store.go +++ b/packages/api/internal/handlers/store.go @@ -62,7 +62,7 @@ type APIStore struct { func NewAPIStore(ctx context.Context, tel *telemetry.Client, config cfg.Config, serviceName string) *APIStore { logger.L().Info(ctx, "Initializing API store and services") - sqlcDB, err := sqlcdb.NewClient(ctx, config.PostgresConnectionString, pool.WithMaxConnections(40), pool.WithMinIdle(5)) + sqlcDB, err := sqlcdb.NewClient(ctx, config.PostgresConnectionString, pool.WithMaxConnections(config.DBMaxOpenConnections), pool.WithMinIdle(config.DBMinIdleConnections)) if err != nil { logger.L().Fatal(ctx, "Initializing SQLC client", zap.Error(err)) } From 409f98ff62b7a745d721c277e4230da554970c34 Mon Sep 17 00:00:00 2001 From: Jakub Dobry Date: Mon, 9 Mar 2026 15:14:41 -0700 Subject: [PATCH 2/4] feat(iac): pass DB pool size vars through Terraform --- iac/provider-gcp/Makefile | 4 +++- iac/provider-gcp/main.tf | 2 ++ iac/provider-gcp/nomad/main.tf | 2 ++ iac/provider-gcp/nomad/variables.tf | 8 ++++++++ iac/provider-gcp/variables.tf | 10 ++++++++++ 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/iac/provider-gcp/Makefile b/iac/provider-gcp/Makefile index 5109f8db40..e731084c4c 100644 --- a/iac/provider-gcp/Makefile +++ b/iac/provider-gcp/Makefile @@ -77,7 +77,9 @@ tf_vars := \ $(call tfvar, LOKI_USE_V13_SCHEMA_FROM) \ $(call tfvar, DASHBOARD_API_COUNT) \ $(call tfvar, DEFAULT_PERSISTENT_VOLUME_TYPE) \ - $(call tfvar, PERSISTENT_VOLUME_TYPES) + $(call tfvar, PERSISTENT_VOLUME_TYPES) \ + $(call tfvar, DB_MAX_OPEN_CONNECTIONS) \ + $(call tfvar, DB_MIN_IDLE_CONNECTIONS) .PHONY: init init: diff --git a/iac/provider-gcp/main.tf b/iac/provider-gcp/main.tf index 485bc0efaa..132b644660 100644 --- a/iac/provider-gcp/main.tf +++ b/iac/provider-gcp/main.tf @@ -221,6 +221,8 @@ module "nomad" { redis_tls_ca_base64_secret_version = module.init.redis_tls_ca_base64_secret_version sandbox_access_token_hash_seed = random_password.sandbox_access_token_hash_seed.result sandbox_storage_backend = var.sandbox_storage_backend + db_max_open_connections = var.db_max_open_connections + db_min_idle_connections = var.db_min_idle_connections # Click Proxy client_proxy_count = var.client_proxy_count diff --git a/iac/provider-gcp/nomad/main.tf b/iac/provider-gcp/nomad/main.tf index 2a61d92f83..4b72b7af17 100644 --- a/iac/provider-gcp/nomad/main.tf +++ b/iac/provider-gcp/nomad/main.tf @@ -101,6 +101,8 @@ module "api" { loki_url = local.loki_url sandbox_access_token_hash_seed = var.sandbox_access_token_hash_seed sandbox_storage_backend = var.sandbox_storage_backend + db_max_open_connections = var.db_max_open_connections + db_min_idle_connections = var.db_min_idle_connections db_migrator_docker_image = data.google_artifact_registry_docker_image.db_migrator_image.self_link launch_darkly_api_key = trimspace(data.google_secret_manager_secret_version.launch_darkly_api_key.secret_data) default_persistent_volume_type = var.default_persistent_volume_type diff --git a/iac/provider-gcp/nomad/variables.tf b/iac/provider-gcp/nomad/variables.tf index f498ba93c2..a18c8a792a 100644 --- a/iac/provider-gcp/nomad/variables.tf +++ b/iac/provider-gcp/nomad/variables.tf @@ -102,6 +102,14 @@ variable "sandbox_storage_backend" { default = "memory" } +variable "db_max_open_connections" { + type = number +} + +variable "db_min_idle_connections" { + type = number +} + variable "environment" { type = string } diff --git a/iac/provider-gcp/variables.tf b/iac/provider-gcp/variables.tf index 9bc9b3bbb7..7b68d7d27a 100644 --- a/iac/provider-gcp/variables.tf +++ b/iac/provider-gcp/variables.tf @@ -615,6 +615,16 @@ variable "sandbox_storage_backend" { default = "" } +variable "db_max_open_connections" { + type = number + default = 40 +} + +variable "db_min_idle_connections" { + type = number + default = 5 +} + variable "loki_use_v13_schema_from" { type = string description = "This should be a date soon after you deploy. Format = YYYY-MM-DD" From c1ceee22826e36b32bfaa507e43fc303a0a3181b Mon Sep 17 00:00:00 2001 From: Jakub Dobry Date: Mon, 9 Mar 2026 22:40:54 +0000 Subject: [PATCH 3/4] feat(iac): wire auth DB pool size vars through Terraform pipeline Add AUTH_DB_MAX_OPEN_CONNECTIONS and AUTH_DB_MIN_IDLE_CONNECTIONS to the full Terraform -> Nomad chain (Makefile, provider-gcp variables, nomad variables, job-api module, HCL template) so auth DB pool sizes can be tuned per environment. --- iac/modules/job-api/jobs/api.hcl | 2 ++ iac/modules/job-api/main.tf | 2 ++ iac/modules/job-api/variables.tf | 10 ++++++++++ iac/provider-gcp/Makefile | 4 +++- iac/provider-gcp/main.tf | 2 ++ iac/provider-gcp/nomad/main.tf | 2 ++ iac/provider-gcp/nomad/variables.tf | 8 ++++++++ iac/provider-gcp/variables.tf | 10 ++++++++++ 8 files changed, 39 insertions(+), 1 deletion(-) diff --git a/iac/modules/job-api/jobs/api.hcl b/iac/modules/job-api/jobs/api.hcl index 47890160f1..972464bf5c 100644 --- a/iac/modules/job-api/jobs/api.hcl +++ b/iac/modules/job-api/jobs/api.hcl @@ -123,6 +123,8 @@ job "api" { DB_MIN_IDLE_CONNECTIONS = "${db_min_idle_connections}" AUTH_DB_CONNECTION_STRING = "${postgres_connection_string}" AUTH_DB_READ_REPLICA_CONNECTION_STRING = "${postgres_read_replica_connection_string}" + AUTH_DB_MAX_OPEN_CONNECTIONS = "${auth_db_max_open_connections}" + AUTH_DB_MIN_IDLE_CONNECTIONS = "${auth_db_min_idle_connections}" SUPABASE_JWT_SECRETS = "${supabase_jwt_secrets}" LOKI_URL = "${loki_url}" diff --git a/iac/modules/job-api/main.tf b/iac/modules/job-api/main.tf index fcc8e0d8f0..f27b6eea1a 100644 --- a/iac/modules/job-api/main.tf +++ b/iac/modules/job-api/main.tf @@ -30,6 +30,8 @@ resource "nomad_job" "api" { redis_tls_ca_base64 = var.redis_tls_ca_base64 db_max_open_connections = var.db_max_open_connections db_min_idle_connections = var.db_min_idle_connections + auth_db_max_open_connections = var.auth_db_max_open_connections + auth_db_min_idle_connections = var.auth_db_min_idle_connections redis_pool_size = var.redis_pool_size clickhouse_connection_string = var.clickhouse_connection_string loki_url = var.loki_url diff --git a/iac/modules/job-api/variables.tf b/iac/modules/job-api/variables.tf index 4d66e43cf0..997c863d09 100644 --- a/iac/modules/job-api/variables.tf +++ b/iac/modules/job-api/variables.tf @@ -135,6 +135,16 @@ variable "db_min_idle_connections" { default = 5 } +variable "auth_db_max_open_connections" { + type = number + default = 20 +} + +variable "auth_db_min_idle_connections" { + type = number + default = 5 +} + variable "redis_pool_size" { type = number default = 160 diff --git a/iac/provider-gcp/Makefile b/iac/provider-gcp/Makefile index e731084c4c..65cf9ece05 100644 --- a/iac/provider-gcp/Makefile +++ b/iac/provider-gcp/Makefile @@ -79,7 +79,9 @@ tf_vars := \ $(call tfvar, DEFAULT_PERSISTENT_VOLUME_TYPE) \ $(call tfvar, PERSISTENT_VOLUME_TYPES) \ $(call tfvar, DB_MAX_OPEN_CONNECTIONS) \ - $(call tfvar, DB_MIN_IDLE_CONNECTIONS) + $(call tfvar, DB_MIN_IDLE_CONNECTIONS) \ + $(call tfvar, AUTH_DB_MAX_OPEN_CONNECTIONS) \ + $(call tfvar, AUTH_DB_MIN_IDLE_CONNECTIONS) .PHONY: init init: diff --git a/iac/provider-gcp/main.tf b/iac/provider-gcp/main.tf index 132b644660..7d43266322 100644 --- a/iac/provider-gcp/main.tf +++ b/iac/provider-gcp/main.tf @@ -223,6 +223,8 @@ module "nomad" { sandbox_storage_backend = var.sandbox_storage_backend db_max_open_connections = var.db_max_open_connections db_min_idle_connections = var.db_min_idle_connections + auth_db_max_open_connections = var.auth_db_max_open_connections + auth_db_min_idle_connections = var.auth_db_min_idle_connections # Click Proxy client_proxy_count = var.client_proxy_count diff --git a/iac/provider-gcp/nomad/main.tf b/iac/provider-gcp/nomad/main.tf index 4b72b7af17..593d68ccd2 100644 --- a/iac/provider-gcp/nomad/main.tf +++ b/iac/provider-gcp/nomad/main.tf @@ -103,6 +103,8 @@ module "api" { sandbox_storage_backend = var.sandbox_storage_backend db_max_open_connections = var.db_max_open_connections db_min_idle_connections = var.db_min_idle_connections + auth_db_max_open_connections = var.auth_db_max_open_connections + auth_db_min_idle_connections = var.auth_db_min_idle_connections db_migrator_docker_image = data.google_artifact_registry_docker_image.db_migrator_image.self_link launch_darkly_api_key = trimspace(data.google_secret_manager_secret_version.launch_darkly_api_key.secret_data) default_persistent_volume_type = var.default_persistent_volume_type diff --git a/iac/provider-gcp/nomad/variables.tf b/iac/provider-gcp/nomad/variables.tf index a18c8a792a..05ed00e22e 100644 --- a/iac/provider-gcp/nomad/variables.tf +++ b/iac/provider-gcp/nomad/variables.tf @@ -110,6 +110,14 @@ variable "db_min_idle_connections" { type = number } +variable "auth_db_max_open_connections" { + type = number +} + +variable "auth_db_min_idle_connections" { + type = number +} + variable "environment" { type = string } diff --git a/iac/provider-gcp/variables.tf b/iac/provider-gcp/variables.tf index 7b68d7d27a..5556cf6556 100644 --- a/iac/provider-gcp/variables.tf +++ b/iac/provider-gcp/variables.tf @@ -625,6 +625,16 @@ variable "db_min_idle_connections" { default = 5 } +variable "auth_db_max_open_connections" { + type = number + default = 20 +} + +variable "auth_db_min_idle_connections" { + type = number + default = 5 +} + variable "loki_use_v13_schema_from" { type = string description = "This should be a date soon after you deploy. Format = YYYY-MM-DD" From 1981678918293d3d38a7223abe86e3aae466ad67 Mon Sep 17 00:00:00 2001 From: Jakub Dobry Date: Mon, 9 Mar 2026 22:43:12 +0000 Subject: [PATCH 4/4] feat(iac): wire DB pool size vars through AWS Terraform pipeline Add DB_MAX_OPEN_CONNECTIONS, DB_MIN_IDLE_CONNECTIONS, AUTH_DB_MAX_OPEN_CONNECTIONS, and AUTH_DB_MIN_IDLE_CONNECTIONS to the AWS provider Terraform chain, matching the GCP setup. --- iac/provider-aws/Makefile | 6 +++++- iac/provider-aws/main.tf | 5 +++++ iac/provider-aws/nomad/main.tf | 4 ++++ iac/provider-aws/nomad/variables.tf | 16 ++++++++++++++++ iac/provider-aws/variables.tf | 20 ++++++++++++++++++++ 5 files changed, 50 insertions(+), 1 deletion(-) diff --git a/iac/provider-aws/Makefile b/iac/provider-aws/Makefile index 1977834a1c..ab8cbe3ac5 100644 --- a/iac/provider-aws/Makefile +++ b/iac/provider-aws/Makefile @@ -34,7 +34,11 @@ tf_vars := AWS_PROFILE=$(AWS_PROFILE) AWS_REGION=$(AWS_REGION) \ $(call tfvar, BUILD_SERVER_MACHINE_TYPE) \ $(call tfvar, BUILD_SERVER_NESTED_VIRTUALIZATION) \ $(call tfvar, AWS_ACCOUNT_ID) \ - $(call tfvar, AWS_REGION) + $(call tfvar, AWS_REGION) \ + $(call tfvar, DB_MAX_OPEN_CONNECTIONS) \ + $(call tfvar, DB_MIN_IDLE_CONNECTIONS) \ + $(call tfvar, AUTH_DB_MAX_OPEN_CONNECTIONS) \ + $(call tfvar, AUTH_DB_MIN_IDLE_CONNECTIONS) .PHONY: provider-login provider-login: diff --git a/iac/provider-aws/main.tf b/iac/provider-aws/main.tf index 06fa70da1d..8bb3eb0d95 100644 --- a/iac/provider-aws/main.tf +++ b/iac/provider-aws/main.tf @@ -220,6 +220,11 @@ module "nomad" { clickhouse_migrator_repository_name = module.init.clickhouse_migrator_repository_name launch_darkly_api_key = module.init.launch_darkly_api_key + + db_max_open_connections = var.db_max_open_connections + db_min_idle_connections = var.db_min_idle_connections + auth_db_max_open_connections = var.auth_db_max_open_connections + auth_db_min_idle_connections = var.auth_db_min_idle_connections } resource "aws_security_group" "cluster_node" { diff --git a/iac/provider-aws/nomad/main.tf b/iac/provider-aws/nomad/main.tf index ddb41dec61..f274006cb2 100644 --- a/iac/provider-aws/nomad/main.tf +++ b/iac/provider-aws/nomad/main.tf @@ -106,6 +106,10 @@ module "api" { db_migrator_docker_image = "${var.aws_account_id}.dkr.ecr.${var.aws_region}.amazonaws.com/${var.db_migrator_repository_name}:latest" loki_url = "http://loki.service.consul:${var.loki_port}" launch_darkly_api_key = var.launch_darkly_api_key + db_max_open_connections = var.db_max_open_connections + db_min_idle_connections = var.db_min_idle_connections + auth_db_max_open_connections = var.auth_db_max_open_connections + auth_db_min_idle_connections = var.auth_db_min_idle_connections } data "aws_s3_object" "orchestrator" { diff --git a/iac/provider-aws/nomad/variables.tf b/iac/provider-aws/nomad/variables.tf index 5b914e9c32..c1dbe21ae2 100644 --- a/iac/provider-aws/nomad/variables.tf +++ b/iac/provider-aws/nomad/variables.tf @@ -296,3 +296,19 @@ variable "launch_darkly_api_key" { default = "" sensitive = true } + +variable "db_max_open_connections" { + type = number +} + +variable "db_min_idle_connections" { + type = number +} + +variable "auth_db_max_open_connections" { + type = number +} + +variable "auth_db_min_idle_connections" { + type = number +} diff --git a/iac/provider-aws/variables.tf b/iac/provider-aws/variables.tf index 407b441bc2..7ae14d58a8 100644 --- a/iac/provider-aws/variables.tf +++ b/iac/provider-aws/variables.tf @@ -143,3 +143,23 @@ variable "control_server_cluster_size" { type = number default = 3 } + +variable "db_max_open_connections" { + type = number + default = 40 +} + +variable "db_min_idle_connections" { + type = number + default = 5 +} + +variable "auth_db_max_open_connections" { + type = number + default = 20 +} + +variable "auth_db_min_idle_connections" { + type = number + default = 5 +}