This check flags Cloud SQL for PostgreSQL instances where the log_disconnections flag is off, leaving you blind to when and how database sessions end. Turn it on by setting the database flag with a single gcloud sql instances patch command.
Connection-level logging is one of those things nobody thinks about until they need it. When a security incident hits or an auditor asks who touched the database and when, the answer lives in your logs. If disconnection logging is disabled on your Cloud SQL PostgreSQL instance, half that picture is missing.
This check looks at the log_disconnections database flag on your GCP Cloud SQL PostgreSQL instances and fails if it is not set to on.
What this check detects
PostgreSQL has two related flags that control session-level logging:
log_connectionslogs each successful connection attempt, including the authenticated user and source.log_disconnectionslogs the end of each session, including the session duration.
This check specifically targets log_disconnections. When it is disabled, PostgreSQL writes nothing when a session closes. You lose the disconnect timestamp and the session duration that PostgreSQL would otherwise calculate for you.
A typical disconnection log line looks like this:
LOG: disconnection: session time: 0:02:14.872 user=app_user database=orders host=10.4.2.17 port=54122
Note: On Cloud SQL, these are exposed as instance-level database flags rather than entries in a postgresql.conf file you can edit directly. You manage them through the Cloud SQL API, the console, or gcloud.
Why it matters
Connection logs without disconnection logs give you half a story. You can see that a user logged in, but you cannot see when they left or how long they stayed connected. That gap matters in several concrete ways.
Incident investigation
Suppose credentials for a service account leak and someone uses them to pull data at 3 a.m. With both flags enabled, you can reconstruct the full session: connect time, source IP, user, and the exact session duration. With disconnections disabled, you know the attacker got in but you cannot bound how long they were rummaging around. That uncertainty turns a tidy timeline into a guess, and guesses do not hold up well in a breach report.
Detecting abnormal session patterns
Session duration is a useful signal. A connection from an application pool that normally lives for seconds but suddenly stays open for an hour is worth a look. Without disconnection events, you cannot compute that duration from logs, so anomaly detection built on session length has nothing to work with.
Compliance and audit
Frameworks like PCI DSS, SOC 2, and HIPAA expect you to track access to systems holding sensitive data. The CIS Google Cloud Platform Foundations Benchmark explicitly recommends enabling log_disconnections for Cloud SQL PostgreSQL instances. If you are subject to any of these, a disabled flag is a finding waiting to happen during your next audit.
Warning: Connection and disconnection logging adds log volume, and on a busy instance with short-lived connections that volume can be significant. Cloud Logging ingestion is billed per gigabyte beyond the free tier, so factor the cost into your decision and consider tuning connection pooling if your apps open and close connections rapidly.
How to fix it
You enable disconnection logging by setting the log_disconnections database flag to on. Here are three ways to do it.
Option 1: gcloud CLI
First, check the current flags so you do not clobber existing ones:
gcloud sql instances describe INSTANCE_NAME \
--project=PROJECT_ID \
--format="value(settings.databaseFlags)"
The patch command replaces the full set of database flags, so you must include any flags you already have. To enable both connection and disconnection logging together:
gcloud sql instances patch INSTANCE_NAME \
--project=PROJECT_ID \
--database-flags=log_connections=on,log_disconnections=on
Danger: The --database-flags argument overwrites all existing flags rather than merging. If your instance already has flags set (for example max_connections or log_min_duration_statement), include every one of them in the same command. Omitting a flag silently removes it.
If you had existing flags, your command should list them all, for example:
gcloud sql instances patch INSTANCE_NAME \
--project=PROJECT_ID \
--database-flags=max_connections=200,log_min_duration_statement=1000,log_connections=on,log_disconnections=on
Note: log_disconnections is a dynamic flag on Cloud SQL, so applying it does not require a restart. The change takes effect for new sessions without downtime.
Option 2: Google Cloud console
- Open SQL in the Cloud console and select your PostgreSQL instance.
- Click Edit.
- Expand the Flags section.
- Click Add a database flag, choose
log_disconnections, and set the value toon. - Click Save.
Option 3: Terraform
If you manage Cloud SQL with Terraform, declare the flag on the instance resource:
resource "google_sql_database_instance" "postgres" {
name = "orders-db"
database_version = "POSTGRES_15"
region = "us-central1"
settings {
tier = "db-custom-2-7680"
database_flags {
name = "log_connections"
value = "on"
}
database_flags {
name = "log_disconnections"
value = "on"
}
}
}
Run terraform plan to confirm the change is limited to the flag, then terraform apply.
Tip: Define the flag once in a reusable module and apply it across every Cloud SQL instance in your fleet. That way a new database inherits the right logging posture the moment it is created, instead of waiting for a scanner to catch it later.
How to prevent it from happening again
Fixing one instance is easy. Keeping every instance compliant as your environment grows is the real work. A few approaches scale better than manual checks.
Enforce with policy-as-code
If you provision through Terraform, gate merges with a policy check. Here is an Open Policy Agent (Rego) rule that denies a plan unless log_disconnections is set to on:
package terraform.cloudsql
deny[msg] {
resource := input.resource_changes[_]
resource.type == "google_sql_database_instance"
flags := resource.change.after.settings[_].database_flags
not has_flag(flags, "log_disconnections", "on")
msg := sprintf("Cloud SQL instance %q must set log_disconnections=on", [resource.address])
}
has_flag(flags, name, value) {
flags[_].name == name
flags[_].value == value
}
Wire this into CI with conftest or Sentinel so a non-compliant plan fails the pipeline before it reaches production.
Catch drift with Organization Policy and asset feeds
Policy-as-code stops bad config at the gate, but it does not catch changes made directly through the console or CLI by someone bypassing your pipeline. Pair it with continuous monitoring. Cloud Asset Inventory feeds can stream Cloud SQL configuration changes to a Pub/Sub topic, where a Cloud Function checks the flags and alerts on regressions.
Tip: Lensix runs the sql_pgdisconnections check continuously across your GCP projects, so a flag flipped off out-of-band shows up as a finding without you wiring up asset feeds and functions yourself.
Best practices
- Enable connection and disconnection logging together. One without the other gives an incomplete session record. Set both
log_connectionsandlog_disconnectionstoon. - Route logs somewhere durable. Logging the events is only useful if the logs survive. Confirm Cloud SQL logs flow into Cloud Logging and set up a log sink to a retention bucket or BigQuery for long-term audit needs.
- Pair with statement logging where it makes sense. For high-sensitivity databases, consider
log_min_duration_statementorpgauditto capture what queries ran, not just who connected. - Use connection pooling to control log volume. Pools like PgBouncer or Cloud SQL Auth Proxy connection management keep session churn low, which keeps your connection and disconnection logs meaningful rather than noisy.
- Apply flags through IaC, not the console. Console changes drift and disappear from your audit trail. Managing flags in Terraform keeps logging configuration reviewable and reproducible.
Disconnection logging is cheap to enable and pays off the moment you need to reconstruct what happened on a database. Turn it on, enforce it in your pipeline, and monitor for drift, and you close a small gap that auditors and incident responders both care about.

