The GCP documentation presents Cloud Run + Cloud SQL as a three-step exercise: add --add-cloudsql-instances, set your socket path, deploy. That description holds until you touch IAM auth, non-trivial passwords, schema migrations, or controlled traffic routing. At that point, the real operational behavior surfaces - and the error messages almost never point to the actual cause.

I run this stack at home on production-grade workloads. What follows is an accounting of five failure categories I hit, what each error said, what actually broke, and what fixed it.

Error Messages Lie Here More Than Anywhere Else

The thread connecting all five problems is misdirection. A password parsing failure reports connection refused. A MySQL authentication incompatibility reports Access denied as if the password is wrong. A cold-start race condition reports a timeout as if the migration is slow. None of these error messages name the actual problem. That gap is what makes debugging this stack expensive.

The five failure categories, and their tested workarounds:

Passwords embedded in DATABASE_URL strings break silently. Any special character with syntactic meaning in a URI - @, #, $, % - splits or corrupts the parsed host, port, or credentials. The reported error is connection refused or host not found, which points at network, not string parsing. The fix: pass credentials as discrete parameters to your database driver. Never embed a password in a URL string. This also eliminates a class of framework-specific double-encoding bugs.

MySQL 8.4 broke unix socket authentication until proxy v2.19.0. MySQL 8.4 changed its handshake so the server always advertises caching_sha2_password, regardless of configured defaults. Older Cloud SQL Auth Proxy releases did not support this plugin over unix sockets. The failure reports ERROR 1045 (28000): Access denied - identical to a wrong password. This was tracked as a P0 in the proxy's GitHub issues (#2317) and fixed in v2.19.0. If you pin the proxy sidecar, pin v2.19.0 or later. If you cannot control the proxy version, use TCP or a Language Connector.

On-boot migrations fail under Cloud Run's scaling model. Running migrations inside the startup sequence creates two concurrent problems. Multiple instances race each other against the same schema version table, and Cloud Run's four-minute startup window kills a slow migration mid-execution. The correct pattern is Cloud Run Jobs - a blocking pipeline step that runs before the new revision deploys.

Cloud Run promotes new revisions immediately by default. If a migration adds a NOT NULL column, the old revision starts failing inserts the moment the migration runs. Cloud Run has no built-in primitive for "hold until migration succeeds, then promote." That orchestration requires --no-traffic with revision tags and an explicit update-traffic call in your pipeline.

Connection pools multiply with instances. Cloud Run scales horizontally, and each instance initializes its own pool. A pool size of 10 across 20 instances creates 200 active connections - often exceeding Cloud SQL's max_connections limit. The Auth Proxy does not pool; it passes each application connection through to the database. Fixing this requires either Cloud SQL Managed Connection Pooling, a PgBouncer sidecar, or aggressively small per-instance pool sizes.

What to Change

These five problems share a common pattern: the default configuration optimizes for simplicity of initial setup, not for correctness under load or non-trivial operational conditions. In this environment, the changes that eliminated most of the friction were:

  • Pass credentials as discrete parameters; use Secret Manager with --set-secrets
  • Run migrations as Cloud Run Jobs with --wait in the pipeline, gated before revision deploy
  • Use --no-traffic plus revision tags for any migration that changes column constraints
  • Set per-instance pool size to 1-5 in this deployment; use Cloud SQL Managed Connection Pooling for PostgreSQL
  • Use the sidecar pattern with container-dependencies ordering, or switch to Language Connectors for MySQL 8.4

The technical layer below covers each problem in detail: the error, the mechanism, the workaround, and the remaining open issues.