Connect Django to Google Cloud SQL
Connect Django to Cloud SQL for PostgreSQL securely: use the Cloud SQL Auth Proxy or Unix sockets on Cloud Run, private IP inside a VPC, IAM database authentication, connection limits, and running migrations against Cloud SQL.
Problem statement
Cloud SQL is Google Cloud's managed PostgreSQL (and MySQL). Connecting Django to it is easy to get wrong: exposing a public IP with an allow-list is fragile, connections without TLS are unsafe, and serverless platforms can open more connections than a small instance allows. Google provides several connection paths, the Cloud SQL Auth Proxy, built-in Unix sockets on Cloud Run, and private IP, each suited to a different runtime. Choosing the right one makes the connection secure without managing certificates or firewall rules.
- Cloud Run: add the instance connection to the service and set
HOST=/cloudsql/PROJECT:REGION:INSTANCE. - GKE or Compute Engine: run the Cloud SQL Auth Proxy (sidecar or local service) and connect to
127.0.0.1:5432. - Inside a VPC: private IP plus
sslmode=requireis fine, especially with the proxy's--private-ipflag. - Grant the runtime service account
roles/cloudsql.client; optionally use IAM database authentication. - Keep connections within the instance's
max_connections: limit Cloud Run instances and Gunicorn workers. - Run migrations from a Cloud Run job or a machine with the proxy.
Step-by-step solution
1. Cloud Run: Unix socket
gcloud run deploy myapp --image REGION-docker.pkg.dev/PROJECT/apps/myapp:SHA \
--add-cloudsql-instances PROJECT:REGION:INSTANCE \
--set-secrets DATABASE_PASSWORD=db-password:latest \
--service-account django-run@PROJECT.iam.gserviceaccount.com
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "app", "USER": "app",
"PASSWORD": env("DATABASE_PASSWORD"),
"HOST": "/cloudsql/PROJECT:REGION:INSTANCE",
"CONN_MAX_AGE": 60,
"CONN_HEALTH_CHECKS": True,
}
}
Cloud Run mounts a socket that the platform connects to Cloud SQL with TLS and IAM; there is no proxy to run yourself.
2. GKE or VMs: Cloud SQL Auth Proxy
./cloud-sql-proxy --port 5432 --private-ip PROJECT:REGION:INSTANCE
On a VM, run it as a systemd service; on GKE, as a native sidecar with Workload Identity. Django connects to 127.0.0.1:5432 with sslmode=disable to the proxy, because the proxy itself encrypts the connection to Cloud SQL.
3. IAM database authentication (optional)
Create a database user for the service account and let the proxy or Cloud Run log in with IAM instead of a password:
gcloud sql users create django-run@PROJECT.iam --instance INSTANCE --type cloud_iam_service_account
./cloud-sql-proxy --auto-iam-authn --port 5432 PROJECT:REGION:INSTANCE
DATABASES["default"].update({"USER": "django-run@PROJECT.iam", "PASSWORD": ""})
Grant that user privileges on the app database. No password exists to rotate or leak.
4. Respect connection limits
Small Cloud SQL tiers allow few connections (max_connections scales with memory). Total connections are roughly instances × Gunicorn workers × 1 (or more with threads). On Cloud Run, cap --max-instances and use few workers per instance; on GKE, cap replicas or add PgBouncer. Monitor database/postgresql/num_backends in Cloud Monitoring. See Fix Postgres Too Many Connections in Django.
5. Run migrations
On Cloud Run, create a job with the same image and Cloud SQL connection:
gcloud run jobs create migrate --image REGION-docker.pkg.dev/PROJECT/apps/myapp:SHA \
--set-cloudsql-instances PROJECT:REGION:INSTANCE --command python --args manage.py,migrate,--noinput
gcloud run jobs execute migrate --wait
On GKE, use a Kubernetes Job with the proxy sidecar.
Verification check: python manage.py dbshell -c "select current_user, inet_server_addr();" works from the runtime, Cloud SQL's Connections page shows the expected clients, and the migration job completes successfully.
Explanation
The Cloud SQL Auth Proxy and Cloud Run's built-in socket both use the Cloud SQL Admin API to fetch ephemeral certificates for the instance, authenticated by the runtime's service account. The client side sees a plain local socket, while traffic to Cloud SQL is encrypted and authorised by IAM. That removes the two classic weaknesses of database connectivity, network allow-lists and certificate management, and lets access follow IAM grants. Private IP keeps traffic within the VPC when you want to avoid public endpoints entirely.
Edge cases / notes
- Python Connector. Google's Cloud SQL Python Connector supports
pg8000and other drivers but notpsycopg, which Django uses; prefer the proxy or sockets. - High availability instances fail over in under a minute;
CONN_HEALTH_CHECKShelps Django recover. - Read replicas have their own connection names; add them as separate Django databases.
- Maintenance windows restart instances; schedule them for quiet hours.
Next steps
- Platform guides: Deploy Django on Google Cloud Run and Deploy Django on GKE.
- General managed database tips: Configure Managed PostgreSQL for Django.
FAQ
How does Django connect to Cloud SQL from Cloud Run?
Through the built-in Unix socket: add the Cloud SQL connection and set HOST to /cloudsql/PROJECT:REGION:INSTANCE.
Do I need the Cloud SQL Auth Proxy?
On GKE, VMs, or outside Google Cloud, yes, unless you use private IP with TLS. Cloud Run has it built in.
Can Django use IAM authentication with Cloud SQL?
Yes, through the proxy's --auto-iam-authn or Cloud Run's IAM socket, with a Cloud SQL IAM user.
Why do I get too many connections on Cloud SQL?
Autoscaled instances times workers exceed max_connections. Cap instances and workers or add a pooler.