{"record":{"id":"07986330106b83c1","repo":"block/buzz","slug":"db-connection-failed-e","errorCode":null,"errorMessage":"DB connection failed: {e}","messagePattern":"DB connection failed: (.+?)","errorType":"console","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/buzz-relay/src/main.rs","lineNumber":261,"sourceCode":"    metrics::gauge!(\"buzz_push_enabled\").set(if config.push_enabled { 1.0 } else { 0.0 });\n    info!(\n        port = config.metrics_port,\n        idle_timeout_secs = usage_idle_timeout_secs,\n        \"Prometheus metrics exporter started\"\n    );\n\n    let db_config = DbConfig {\n        database_url: config.database_url.clone(),\n        read_database_url: config.read_database_url.clone(),\n        replica_read_max_age_ms: config.replica_read_max_age_ms,\n        max_connections: config.db_pool_size,\n        read_max_connections: config.db_read_pool_size,\n        ..DbConfig::default()\n    }\n    .with_session_timeouts_from_env();\n    let db = Db::new(&db_config).await.map_err(|e| {\n        error!(\"Failed to connect to Postgres: {e}\");\n        anyhow::anyhow!(\"DB connection failed: {e}\")\n    })?;\n    if db.has_read_pool() {\n        info!(\"Postgres connected (writer + lazy read replica pool)\");\n        // Reader-down at boot must not crash or block the relay; this warn-only\n        // ping is the sole boot-time visibility that the replica is unreachable\n        // (the lazy pool with min_connections=0 dials nothing until first use).\n        db.spawn_read_pool_boot_ping();\n    } else {\n        info!(\"Postgres connected\");\n    }\n\n    let auto_migrate =\n        buzz_auto_migrate_enabled(std::env::var(\"BUZZ_AUTO_MIGRATE\").ok().as_deref());\n    if auto_migrate {\n        db.migrate().await.map_err(|e| {\n            error!(\"Failed to run database migrations: {e}\");\n            anyhow::anyhow!(\"Database migration failed: {e}\")\n        })?;","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/block/buzz/blob/ef2aa1ae38fadcc0bc22b8bf6ed96b35933146be/crates/buzz-relay/src/main.rs#L243-L279","documentation":"Fatal startup error: Db::new() failed to establish the Postgres connection pool for the event store. The underlying sqlx error is logged as `Failed to connect to Postgres: {e}` before this wrap; because every relay path needs the DB, startup aborts.","triggerScenarios":"DATABASE_URL points at a Postgres that is down, unreachable (network/firewall/DNS), has wrong credentials, or the database does not exist. Also triggered by an SSL/TLS requirement mismatch or Postgres already at max_connections.","commonSituations":"Docker Compose / Kubernetes starting the relay before Postgres passes its healthcheck; rotated DB password not updated in the secret; DATABASE_URL copied between environments; local dev without `just setup` having run migrations or started the DB.","solutions":["Confirm Postgres is reachable with the same URL: psql \"$DATABASE_URL\" -c 'select 1'","Fix credentials, host, port, or database name in DATABASE_URL (and BUZZ_READ_DATABASE_URL if set)","Add a depends_on healthcheck (or init container) so the relay only starts once Postgres accepts connections","If Postgres reports too many connections, raise max_connections or lower BUZZ_DB_POOL_SIZE"],"exampleFix":"# docker-compose: before\nservices:\n  relay:\n    image: buzz-relay\n    # starts immediately, loses the race with postgres\n\n# after\nservices:\n  relay:\n    image: buzz-relay\n    depends_on:\n      postgres:\n        condition: service_healthy\n  postgres:\n    healthcheck:\n      test: [\"CMD-SHELL\", \"pg_isready -U $${POSTGRES_USER}\"]\n      interval: 2s\n      retries: 15","handlingStrategy":"retry","validationCode":"# Boot gate before starting the relay:\nuntil psql \"$DATABASE_URL\" -c 'select 1' >/dev/null 2>&1; do\n  echo 'waiting for postgres'; sleep 1\ndone\nexec ./buzz-relay","typeGuard":null,"tryCatchPattern":"// In a supervisor wrapper: retry the relay process with backoff only for\n// db-connect failures at boot; config errors (42) must not be retried.","preventionTips":["Gate relay startup on a Postgres healthcheck (depends_on: condition: service_healthy)","Rotate DB credentials via the same pipeline that restarts the relay","Monitor Postgres connection headroom against BUZZ_DB_POOL_SIZE plus audit/search pools"],"tags":["postgres","database","connection","startup","buzz-relay"],"backgroundTag":"database-connection-failed","analyzedSha":"ef2aa1ae38fadcc0bc22b8bf6ed96b35933146be","analyzedAt":"2026-09-05T18:13:50.666Z","contentChangedAt":"2026-09-05T18:13:50.666Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}