How to Fix Cloud SQL Connection Refused in GCP
“Connection refused” from Cloud SQL means your application cannot reach the database listener. The fix depends on whether the problem is in your connection method, the network path, or the database authentication layer. This guide walks through each failure type with exact commands to diagnose and fix it.
Cloud SQL connection errors split into three categories: transport failures (connection refused, timeout), SSL/TLS rejections, and database-level authentication failures. Each has a different root cause and a different fix. Start with the quick-diagnosis table below to match your error message, then jump to the relevant fix section.
Simple explanation: where Cloud SQL connections break
When your application connects to Cloud SQL, the request passes through several layers. A failure at any layer produces a different error message.
Connecting to Cloud SQL is like dialling a phone number. First, you need the right number (host and port). Then, the call has to route through the network (VPC, peering, internet). The phone on the other end has to be plugged in and ringing (Cloud SQL instance running). Finally, the person who picks up has to recognise you (database authentication). “Connection refused” is like getting a “this number is not in service” tone. “Connection timed out” is like the call never connecting at all, just silence. “Authentication failed” is like someone answering but not letting you in because you gave the wrong name.
Here is the path from your app to the database:
- Your application or client sends a connection request to a host and port (or Unix socket).
- Proxy or connector handles IAM auth and encryption. This could be the Cloud SQL Auth Proxy, a language connector, or the Cloud Run built-in connector.
- Network path carries traffic through your VPC, VPC peering, or the public internet to reach the Cloud SQL instance.
- Cloud SQL instance is the managed database engine that listens for incoming connections.
- Database authentication is the final gate where the engine checks username, password or IAM token, SSL requirements, and grants.
“Connection refused” almost always means nothing is listening where your app is trying to connect: wrong host, wrong port, proxy not running, or wrong connection method. “Connection timed out” usually means the network path is broken: wrong VPC, missing peering, or a firewall blocking traffic. “Password authentication failed” or “SSL required” means the connection reached the database but was rejected at the auth layer.
Quick diagnosis: match your error to the fix
Find your error message in the table below. Each row points to the most likely cause and the section that covers the fix.
| Symptom / error message | Most likely cause | What to check first | Go to |
|---|---|---|---|
| ECONNREFUSED / connection refused on 127.0.0.1 | Auth Proxy not running, or app pointed at wrong port | Is the proxy process running? Does the port match? | Fix 1 |
| Connection refused on Cloud Run | App using TCP (127.0.0.1) instead of Unix socket | Connection string should use /cloudsql/… socket path | Fix 2 |
| Connection timed out | Network path broken: wrong VPC, missing peering, or firewall | Is the client in the same VPC (or peered VPC) as Cloud SQL? | Fix 3 |
| Private IP unreachable | Client is outside the peered VPC, or VPC peering is not configured | Run gcloud sql instances describe and compare the VPC | Fix 3 |
| SSL required / SSL connection error | Instance requires SSL but client is not using it | Check sslMode on the instance | Fix 5 |
| Password authentication failed | Wrong credentials or user does not exist | List users with gcloud sql users list | Fix 5 |
| Cloud SQL Admin API has not been used | API not enabled or IAM permissions missing | Enable the API; grant roles/cloudsql.client | Fix 1 |
How Cloud SQL connections work
Cloud SQL supports three main connection patterns. Choosing the wrong one is the most common cause of connection failures.
Cloud SQL Auth Proxy and language connectors
The Auth Proxy runs as a local process (or sidecar) and creates an authenticated, encrypted tunnel to Cloud SQL. Your application connects to 127.0.0.1 or a Unix socket, and the proxy handles IAM auth and TLS behind the scenes. Language-specific connectors (Python, Java, Go, Node.js) do the same thing as a library instead of a sidecar.
Best for: local development, GKE sidecars, VMs, and any environment where you want automatic certificate management. This is the recommended secure connection method.
Private IP (direct TCP)
Cloud SQL allocates a private IP address inside your VPC via private services access (VPC peering with Google). Applications in the same VPC connect directly over TCP without a proxy.
Best for: production services that already run inside the VPC and need minimal latency or cannot run a sidecar.
Public IP with authorised networks
Cloud SQL exposes a public IP and you allowlist specific client CIDRs. Traffic goes over the internet (encrypted by SSL).
Best for: quick testing, legacy apps, or environments where running a proxy is not possible. Not recommended for production. Use Auth Proxy or private IP instead.
If you are unsure which connection method your app uses, check your connection string. Connecting to 127.0.0.1? You need the Auth Proxy running locally. Connecting to a 10.x.x.x address? That is a private IP, and you need VPC access. Connecting to a /cloudsql/… path? That is a Unix socket from the Cloud Run built-in connector. Knowing which pattern you are on tells you exactly which fix section to read.
Fix 1: Auth Proxy or Cloud SQL connector issues
Most “connection refused on 127.0.0.1” errors during local development mean the Auth Proxy is not running, is running on a different port, or the service account lacks permissions.
Check that the proxy is running and listening
# Start the Auth Proxy for PostgreSQL on port 5432
./cloud-sql-proxy --port=5432 PROJECT_ID:REGION:INSTANCE_NAME
# For MySQL, use port 3306
./cloud-sql-proxy --port=3306 PROJECT_ID:REGION:INSTANCE_NAME
# Verify it is listening
# Linux/macOS:
ss -tlnp | grep 5432
# Windows:
netstat -an | findstr 5432If the proxy is running but your app still gets connection refused, confirm your app is connecting to exactly the same host and port the proxy is listening on. A mismatch of even one digit causes a refusal.
Grant the required IAM role
The service account running the proxy needs roles/cloudsql.client. Without it, the proxy starts but silently fails every connection attempt. This is the single most common Auth Proxy problem. See Permission Denied Errors for more on IAM troubleshooting.
The Auth Proxy starts successfully even without the right IAM role. It looks healthy, logs no errors on startup, and appears to be listening. But every connection your app makes through it fails. This trips up almost everyone at least once. Always verify roles/cloudsql.client first.
# Grant Cloud SQL Client role to the proxy's service account
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:my-sa@PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/cloudsql.client"Verify the instance connection name
# Get the exact instance connection name
gcloud sql instances describe INSTANCE_NAME \
--format="value(connectionName)"
# Output format: PROJECT_ID:REGION:INSTANCE_NAME
# This must match exactly what you pass to the proxyIf you switch between local development and a deployed environment, remember that locally you connect to 127.0.0.1:PORT via the proxy, but in Cloud Run you connect via a Unix socket. Use environment variables to switch connection strings between environments.
Fix 2: Cloud Run and Cloud Functions connectivity
Cloud Run and Cloud Functions handle Cloud SQL connections differently from VMs or containers. The most common mistake is using a TCP connection string (127.0.0.1:5432) when the platform expects a Unix socket.
Built-in Cloud SQL connector (recommended)
When you attach a Cloud SQL instance to Cloud Run, the platform creates a Unix socket at /cloudsql/PROJECT_ID:REGION:INSTANCE_NAME. Your app must connect to this socket path, not to a TCP host and port.
# Attach the Cloud SQL instance to Cloud Run
gcloud run services update my-service \
--region=REGION \
--add-cloudsql-instances=PROJECT_ID:REGION:INSTANCE_NAME
# In your app, connect to the Unix socket:
# PostgreSQL: host=/cloudsql/PROJECT_ID:REGION:INSTANCE_NAME
# MySQL: socket=/cloudsql/PROJECT_ID:REGION:INSTANCE_NAME
# Do NOT use: host=127.0.0.1 port=5432If your connection string uses 127.0.0.1 or localhost on Cloud Run, you will get “connection refused” every time. Nothing listens on TCP ports. The connector only exposes a Unix socket.
On your local machine, the Auth Proxy opens a TCP “door” at 127.0.0.1:5432 and your app walks through it. On Cloud Run, the built-in connector opens a different kind of “door”: a Unix socket file at /cloudsql/…. If your app keeps knocking on the TCP door that does not exist on Cloud Run, nobody answers. You need to change which door your app is looking for.
Service account permissions
The Cloud Run (or Cloud Functions) service account needs roles/cloudsql.client. If the service account lacks this role, connections fail with an authentication error from the Cloud SQL API even though the socket path is correct.
# Check the service account used by your Cloud Run service
gcloud run services describe my-service \
--region=REGION \
--format="value(spec.template.spec.serviceAccountName)"
# Grant the role
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
--role="roles/cloudsql.client"Private IP options for serverless workloads
If you need to connect to Cloud SQL via private IP from Cloud Run (instead of using the built-in connector), you have several options:
- Direct VPC egress lets Cloud Run send traffic directly into your VPC without a separate connector resource. Configure this with
—networkand—subnetflags, or through the VPC access settings in the console. This avoids the overhead of a dedicated Serverless VPC Access connector. - Serverless VPC Access connector is a dedicated connector resource that routes traffic from Cloud Run into your VPC. Still supported and works well, but direct VPC egress is simpler for new deployments.
# Option A: Direct VPC egress (no separate connector needed)
gcloud run services update my-service \
--region=REGION \
--network=my-vpc \
--subnet=my-subnet \
--vpc-egress=private-ranges-only
# Option B: Serverless VPC Access connector
gcloud run services update my-service \
--region=REGION \
--vpc-connector=my-vpc-connector \
--vpc-egress=private-ranges-onlyWith either VPC egress option, you connect to Cloud SQL using its private IP address over TCP (not a Unix socket). Make sure the Cloud SQL instance has a private IP enabled and that the VPC/subnet can route to it.
Fix 3: Private IP routing issues
Cloud SQL private IPs are allocated inside a Google-managed VPC that is peered to your project VPC via private services access. If your application is outside that peered network, the private IP is unreachable and the connection times out.
A Cloud SQL private IP is like an address on a private road inside a gated community (your VPC). If your app is standing outside the gate (different VPC, local machine, or serverless service without VPC access), it cannot reach that address. It is not that the address is wrong. It is that you are on the wrong side of the gate.
Verify the network and peering
# Check which VPC the Cloud SQL instance is peered with
gcloud sql instances describe INSTANCE_NAME \
--format="value(settings.ipConfiguration.privateNetwork)"
# Check whether private services access is configured
gcloud services vpc-peerings list \
--network=my-vpc \
--service=servicenetworking.googleapis.com
# Get the private IP address
gcloud sql instances describe INSTANCE_NAME \
--format="value(ipAddresses[].ipAddress)"Common private IP failures
- Client not in the same VPC. Your VM, GKE pod, or Cloud Run service must be in the VPC that is peered with Cloud SQL, or in a VPC that has connectivity to it. If you are connecting from a different VPC, you need VPC peering or a shared VPC setup.
- Private services access not configured. The
google-managed-services-*peering must exist between your VPC and Google’s service networking. Without it, the private IP range is not routed. - Subnet range conflict. The allocated IP range for private services must not overlap with your existing subnet ranges.
- Timeout vs refused. A timeout means the packet is being dropped (routing issue). A refusal means something is listening but rejecting the connection (wrong port, or the IP belongs to a different service). Use VPC Connectivity Tests to trace the exact failure point.
# Test connectivity from a VM in the same VPC
# Replace PRIVATE_IP with the Cloud SQL private IP
nc -zv PRIVATE_IP 5432
# If this times out, the routing or peering is broken
# If this connects, the network path is fine and the issue is elsewhereFix 4: Public IP and authorised networks
Connecting via public IP without the Auth Proxy requires your source IP to be in the Cloud SQL instance’s authorised networks list. This is a separate allowlist from VPC firewall rules.
When public IP is acceptable
Public IP is fine for quick local testing or one-off admin access. It is weaker operationally than Auth Proxy or private IP because you must maintain an IP allowlist that drifts as your infrastructure changes.
Common public IP mistakes
- Adding your home IP but deploying to cloud. The deployed service has a different egress IP. The connection works locally but fails in production.
- Using broad CIDRs. Adding
0.0.0.0/0opens the database to the entire internet. Never do this. If you need broad access, use the Auth Proxy instead. - Dynamic IP changes. Home ISPs reassign IPs regularly. Your authorised network entry goes stale and connections start failing. The Auth Proxy avoids this entirely.
# Add an authorised network
gcloud sql instances patch INSTANCE_NAME \
--authorized-networks=203.0.113.10/32
# View current authorised networks
gcloud sql instances describe INSTANCE_NAME \
--format="value(settings.ipConfiguration.authorizedNetworks)"
# Check your current external IP
curl -s ifconfig.meNever add 0.0.0.0/0 to authorised networks. That is the equivalent of removing the lock from your front door. Use the Auth Proxy instead, which authenticates every connection via IAM without requiring broad network exposure.
Fix 5: SSL/TLS and database authentication
If the TCP connection reaches the database but is rejected, the problem is at the database engine level. These errors look different from network-level failures. See Troubleshooting Authentication Errors for a deeper guide on auth issues.
SSL mode mismatch
# Check the SSL mode on the instance
gcloud sql instances describe INSTANCE_NAME \
--format="value(settings.ipConfiguration.sslMode)"
# ENCRYPTED_ONLY: SSL required, no client cert needed
# TRUSTED_CLIENT_CERTIFICATE_REQUIRED: SSL + client cert required
# ALLOW_UNENCRYPTED_AND_ENCRYPTED: SSL optionalIf the instance requires SSL and your client connects without it, the connection is dropped immediately. The Auth Proxy handles SSL automatically, so if you use the proxy you do not need to configure SSL in your application.
An SSL rejection looks similar to a network refusal but has a different cause. With a network problem, the TCP handshake never completes. With an SSL mismatch, the TCP handshake succeeds but the TLS handshake fails immediately after. If you are unsure, try connecting with openssl s_client -connect HOST:PORT. If it completes the TLS handshake, your network is fine and the issue is in your app’s SSL configuration.
Wrong username or password
# List database users
gcloud sql users list --instance=INSTANCE_NAME
# Reset a user's password
gcloud sql users set-password USER_NAME \
--instance=INSTANCE_NAME \
--password=NEW_PASSWORDIAM database authentication
IAM database authentication uses IAM tokens instead of passwords. If you configured an IAM user but are passing a password (or vice versa), authentication fails. These are distinct user types. A built-in database user and an IAM database user are not interchangeable.
# Create an IAM-authenticated database user
gcloud sql users create SERVICE_ACCOUNT_EMAIL \
--instance=INSTANCE_NAME \
--type=CLOUD_IAM_SERVICE_ACCOUNT
# The Auth Proxy can handle IAM DB auth automatically:
./cloud-sql-proxy --auto-iam-authn PROJECT_ID:REGION:INSTANCE_NAMEUser exists but has no grants
A user can authenticate successfully but have no permissions on any database. This produces “permission denied” errors at the SQL level, not during connection. Connect as a privileged user and grant the necessary permissions. For PostgreSQL, use GRANT statements. For MySQL, use GRANT or ALTER USER.
When to use this guide
This page covers Cloud SQL connection troubleshooting for these scenarios:
- Local development with the Auth Proxy connecting from your workstation.
- Cloud Run using the built-in Cloud SQL connector, direct VPC egress, or Serverless VPC Access.
- Cloud Functions using the same connector patterns as Cloud Run.
- VMs and GKE connecting via Auth Proxy sidecar, private IP, or public IP.
- Teams using private IP who need to diagnose VPC peering, routing, and private services access issues.
- SSL and IAM auth issues including certificate mismatches, password failures, and IAM token problems.
If your error is not Cloud SQL specific (for example, a general VPC routing problem), see Debugging VPC Connectivity instead.
Auth Proxy vs private IP vs public IP
Choosing the wrong connection method is the root cause of many Cloud SQL failures. Use this table to pick the right one.
| Option | Best for | Main benefit | Main drawback | Typical failure mode |
|---|---|---|---|---|
| Auth Proxy / connectors | Local dev, GKE, VMs, any environment | Automatic IAM auth, encryption, no IP management | Requires running a sidecar or library dependency | Missing roles/cloudsql.client on service account |
| Private IP (direct TCP) | Production VPC workloads, low latency | No proxy overhead, native TCP connection | Only reachable from within the peered VPC | Timeout from outside the VPC; peering not configured |
| Public IP + authorised networks | Quick testing, legacy apps | Simple setup, no VPC required | IP allowlist maintenance, broader attack surface | Stale IP in allowlist; 0.0.0.0/0 exposure |
| Cloud Run built-in connector | Cloud Run and Cloud Functions | Zero config, managed by platform | Unix socket only, so TCP connection strings break | App connects to 127.0.0.1 instead of socket |
Not sure which one to pick? Start with the Auth Proxy. It works in every environment, handles encryption and auth for you, and you can always switch to private IP or a built-in connector later without changing your database configuration.
Common beginner mistakes
Missing
roles/cloudsql.clienton the service account. The Auth Proxy or Cloud Run connector starts fine but every connection fails silently. This is the number one cause of “it was working and now it is not” after a service account change.Using TCP on Cloud Run when the connector expects a Unix socket.
127.0.0.1:5432works locally with the Auth Proxy but fails on Cloud Run. Use the/cloudsql/…socket path instead.Connecting to private IP from outside the VPC. Cloud SQL private IPs are only routable inside the peered VPC. From a local machine or from a Cloud Run service without VPC egress, the connection times out with no useful error message.
Wrong instance connection name. A single character off in
PROJECT_ID:REGION:INSTANCE_NAMEand the Auth Proxy cannot find the instance. Copy the connection name fromgcloud sql instances describerather than typing it manually.Authorised network set for local IP, deployed to cloud. Your laptop IP and your Cloud Run or GKE egress IP are completely different. Authorised networks that work locally break in production. Use the Auth Proxy to avoid IP-dependent config entirely.
Confusing IAM DB auth with built-in passwords. IAM database users authenticate with tokens, not passwords. Passing a password for an IAM user (or a token for a built-in user) always fails. Check the user type with
gcloud sql users list.Forgetting to enable the Cloud SQL Admin API. The Auth Proxy calls the Cloud SQL Admin API to get connection metadata. If the API is not enabled, the proxy fails with a confusing error that does not mention the API directly.
Summary
- ”Connection refused” = nothing listening at that address. Check proxy, port, and connection method.
- ”Connection timed out” = network path broken. Check VPC, peering, and firewall rules.
- ”Authentication failed” = connection reached the DB but credentials or SSL are wrong.
- Auth Proxy needs
roles/cloudsql.client. This is the most common silent failure. - Cloud Run uses Unix sockets, not TCP. Connect to
/cloudsql/PROJECT:REGION:INSTANCE. - Private IP is only reachable inside the peered VPC. Use direct VPC egress or a VPC connector for Cloud Run.
- Avoid public IP with broad CIDRs in production. Use Auth Proxy or private IP.
- Database auth errors (wrong password, SSL required) are separate from transport errors.
Frequently asked questions
Why do I get connection refused even though my Cloud SQL instance is running?
"Connection refused" means nothing is listening at the address and port your application is trying to reach. The Cloud SQL instance may be running, but your client is pointed at the wrong host, wrong port, or the wrong connection method entirely. Common causes: the Auth Proxy is not running, the proxy is listening on a different port than your app expects, or you are connecting to 127.0.0.1 from Cloud Run instead of using the Unix socket path. Check what your application is actually connecting to, not just whether the instance is up.
Should I use Auth Proxy, private IP, or public IP for Cloud SQL?
Use the Cloud SQL Auth Proxy or a language-specific Cloud SQL connector for most workloads. They handle IAM authentication, encryption, and connection management automatically. Use private IP for production services that run inside your VPC and need direct TCP access without a proxy. Use public IP with authorised networks only for quick testing or legacy setups where you cannot run the proxy. For Cloud Run, use the built-in Cloud SQL connector.
Why does Cloud Run fail when I connect to 127.0.0.1?
When you attach a Cloud SQL instance to Cloud Run with --add-cloudsql-instances, the connection is exposed as a Unix socket at /cloudsql/PROJECT:REGION:INSTANCE, not as a TCP listener on 127.0.0.1. If your connection string points to 127.0.0.1:5432 (or 3306), nothing is listening there and you get connection refused. Change your connection string to use the Unix socket path instead.
What is the difference between a connection timeout and connection refused?
"Connection refused" means the target host received your packet but no process was listening on that port, so the OS sent back a TCP RST. "Connection timed out" means your packet never got a response at all, which points to a routing or firewall problem. Refused usually means wrong port, wrong host, or the proxy is not running. Timeout usually means wrong network, missing VPC peering, or a firewall rule blocking traffic.
Is my Cloud SQL error an IAM problem or a network problem?
If you see "connection refused" or "connection timed out," it is a network or proxy problem because the connection never reached the database engine. If you see "password authentication failed," "SSL required," "role does not exist," or "access denied," the TCP connection succeeded and the issue is at the database authentication or SSL layer. Check your error message carefully: network errors come from the OS or proxy, while database errors come from PostgreSQL, MySQL, or SQL Server.