Pattern — a Cloud Run service reaching Cloud SQL with no database credential

The end-to-end handoff for the commonest shape in a Google Cloud application: a Cloud Run service, its own service account, a private-IP Cloud SQL instance, IAM database authentication through a connector, and the three grants that carry it. With the known-bad configurations and the 503 they produce.

markdownpatternv1ANX6-HFVEstage: deploytrust: officialfamily: computeservice: cloud-runinterface: anycloud run to cloud sqlIAM database authenticationroles/cloudsql.clientprivate IPcloud SQL connectorroles/secretmanager.secretAccessor503known-bad configurationconnection poolfailover

Created 21 Oct 2026 · Modified 23 Oct 2026 · 1 version

Cloud Run → Cloud SQL, with no password

The handoff

Cloud Run service  (its OWN service account, attached)
   │  roles/cloudsql.client            ← may open the connection
   │  roles/secretmanager.secretAccessor  ← only if it must read a secret at all
   ▼
Cloud SQL connector  (Language Connector, or the Auth Proxy)
   │  presents a SHORT-LIVED ACCESS TOKEN for the service account
   ▼
Cloud SQL instance  (PRIVATE IP, reachable from the VPC)
   │  the database user IS the IAM principal
   ▼
in-database GRANTs decide what it may read and write

Build order: guides/databases/connect-to-cloud-sql-with-iam-auth.md. The deploy side: guides/compute/deploy-a-container-on-cloud-run.md.

The three gates, which are three different systems

GateDecidesGrant
IAM on the instance's projectmay this identity open a connectionroles/cloudsql.client
the database's own user modelwho it is in the databasean IAM database authentication user
the database's GRANTswhat it may read and writeSQL, not IAM

All three are required and none implies another. An identity with the first two connects successfully and can do nothing — which looks like a broken configuration and is a missing GRANT.

Known-bad configurations

1. A password in Secret Manager

It works. It is still the wrong pattern: a credential exists, so it can leak, must rotate, and appears in an inventory. IAM database authentication removes the credential rather than protecting it. If the design needs a secret at all, make sure the runtime identity has roles/secretmanager.secretAccessor — the viewer role cannot read a payload, and that mistake is the commonest cause of the 503 below.

2. A public IP with an authorized-networks allowlist

The vendor's own instruction: *"If you're connecting to an instance by a public IP address, use a Cloud SQL connector (either the Cloud SQL Auth Proxy or one of the Cloud SQL Language Connectors)."* An address allowlist is the weaker answer and ages badly — Cloud Run egress addresses are not a fixed set unless you make them one.

3. The default service account

The default Compute Engine service account is shared, broadly privileged, and sometimes deleted by a tidy administrator — which produces the deploy-time "User does not have permission to access namespace". One service account per service, passed with --service-account.

4. A connection pool that does not reconnect

Cloud SQL HA fails over to a standby VM in another zone, and a maintenance update requires an instance restart. Both are designed, scheduled events. A pool that treats a dropped connection as fatal turns either one into an outage. Configure the maintenance window too — the default is an arbitrary hour.

5. A pool sized per instance in a service that scales to many instances

Cloud Run scales out. maxConnections is per process, so the database sees pool size × instance count. Size the pool against the instance ceiling, not against one container.

The failure you will actually meet

HTTP 503  The request failed because the instance could not start successfully.

Documented causes: missing secrets, IAM, network. Check in that order:

  1. can the runtime identity read the secret? (secretAccessor, not viewer)
  2. does it hold roles/cloudsql.client?
  3. is the egress path to the private IP open?

A 429 is something else entirely — capacity, not configuration (reference/compute/errors.md §4).

Verification

TestExpected
the service answers a request that touches the database200
grep the whole deployment for a database passwordnothing
remove roles/cloudsql.client and redeploythe connection fails — proving which control carries it
trigger or await a failoverthe service reconnects
scale to the instance ceiling under loadthe database connection count stays within its limit

Read this document as markdown — the same bytes an agent receives.