Back to blog
AzureBest PracticesCloud SecurityDatabasesMonitoring & Logging

PostgreSQL Disconnection Logging Disabled on Azure: Why It Matters and How to Fix It

Learn why disabling log_disconnections on Azure PostgreSQL hurts incident response and audits, plus CLI, Terraform, and Azure Policy fixes to enable it.

TL;DR

This check flags Azure Database for PostgreSQL servers where the log_disconnections parameter is off, meaning you have no record of when sessions end. Turn it on with a single CLI command so you can reconstruct session activity during audits and incident response.

When something goes wrong with a database, the first questions are usually "who connected, when, and for how long?" Connection logging answers the first half of that. Disconnection logging answers the rest. On Azure Database for PostgreSQL, the log_disconnections server parameter controls whether the engine writes a log line every time a session terminates. If it is off, you lose visibility into session lifetime, abnormal terminations, and the full timeline of who was talking to your database.

This Lensix check, postgresql_nologdisconnections, looks at each Azure PostgreSQL server and reports any where disconnection logging is disabled.


What this check detects

The check inspects the log_disconnections server parameter on your Azure Database for PostgreSQL instances. If the value is set to OFF, the server is flagged.

When enabled, PostgreSQL logs a line for every session that ends, including the session duration and the user that owned it. A typical disconnection log entry looks like this:

LOG:  disconnection: session time: 0:02:13.482 user=app_user database=orders host=10.0.1.42

Note: log_disconnections is paired with log_connections. The first records session start, the second records session end and total duration. You generally want both on. This check focuses on disconnections, but it is worth verifying connection logging at the same time.

This applies to the Single Server and Flexible Server deployment models, both of which expose log_disconnections as a configurable server parameter.


Why it matters

Disconnection logging is cheap to enable and disproportionately useful when you actually need it. Here is where the gap bites.

Incident response and forensics

Say you detect data exfiltration or a suspicious query pattern. With connection logs alone, you know a session started. Without disconnection logs, you do not know when it ended or how long the attacker held the connection open. Session duration is often the difference between "they ran one query" and "they sat on this connection for 40 minutes pulling data." That timeline matters when you scope a breach.

Detecting abnormal session behavior

Sessions that disconnect immediately after connecting, sessions that linger far longer than your application's connection pool should allow, or a burst of disconnections during an outage all tell a story. You cannot build that story without the log lines.

Compliance and audit trails

Frameworks like PCI DSS, HIPAA, and SOC 2 expect a complete record of access to systems holding sensitive data. "We log when people connect but not when they leave" is a hard position to defend during an audit. Several CIS benchmarks for Azure database services explicitly call for both connection and disconnection logging.

Warning: Logs are only useful if you keep them. Enabling log_disconnections writes entries to the PostgreSQL logs, but you still need to route those logs to a destination such as Azure Monitor or a Log Analytics workspace and set a retention period that meets your compliance requirements. Enabling the parameter alone does not solve retention.


How to fix it

You can flip this parameter through the Azure CLI, the portal, or infrastructure as code. The parameter is dynamic, so no server restart or downtime is required.

Option 1: Azure CLI

For a Flexible Server:

az postgres flexible-server parameter set \
  --resource-group my-resource-group \
  --server-name my-pg-server \
  --name log_disconnections \
  --value on

For a Single Server:

az postgres server configuration set \
  --resource-group my-resource-group \
  --server-name my-pg-server \
  --name log_disconnections \
  --value on

Confirm the change took effect:

az postgres flexible-server parameter show \
  --resource-group my-resource-group \
  --server-name my-pg-server \
  --name log_disconnections \
  --query "{name:name, value:value}" -o table

Tip: While you are here, enable log_connections with the same command structure, swapping the parameter name. The two together give you full session lifecycle visibility for almost no overhead.

Option 2: Azure Portal

  1. Open your Azure Database for PostgreSQL server in the portal.
  2. Under Settings, select Server parameters.
  3. Search for log_disconnections.
  4. Set the value to ON.
  5. Click Save.

Option 3: Terraform

If you manage your servers with Terraform, add a parameter resource so the setting is enforced in code rather than clicked once and forgotten:

resource "azurerm_postgresql_flexible_server_configuration" "log_disconnections" {
  name      = "log_disconnections"
  server_id = azurerm_postgresql_flexible_server.example.id
  value     = "on"
}

resource "azurerm_postgresql_flexible_server_configuration" "log_connections" {
  name      = "log_connections"
  server_id = azurerm_postgresql_flexible_server.example.id
  value     = "on"
}

Note: The value for these PostgreSQL boolean parameters is the string "on", not true. Using a boolean will cause a plan error.


How to prevent it from coming back

Fixing one server is easy. Keeping every server compliant as your fleet grows is the real work. A few approaches scale better than manual checks.

Azure Policy with deployIfNotExists

Azure Policy can detect and remediate non-compliant servers automatically. Use the built-in policies that audit logging settings for PostgreSQL, or author a custom policy that enforces log_disconnections = on. Assign it at the subscription or management group level so new servers inherit it.

{
  "if": {
    "allOf": [
      {
        "field": "type",
        "equals": "Microsoft.DBforPostgreSQL/flexibleServers/configurations"
      },
      {
        "field": "name",
        "equals": "log_disconnections"
      },
      {
        "field": "Microsoft.DBforPostgreSQL/flexibleServers/configurations/value",
        "notEquals": "on"
      }
    ]
  },
  "then": {
    "effect": "audit"
  }
}

CI/CD gates for infrastructure as code

If your servers are provisioned through Terraform or Bicep, scan the plan before it applies. Tools like Checkov, tfsec, or Terrascan can fail a pipeline when the logging parameter is missing. A simple gate in your pipeline catches the regression before it reaches production:

checkov -d ./infra --check CKV_AZURE_* --compact

Continuous monitoring with Lensix

Policy and CI gates catch new resources, but drift still happens when someone changes a parameter by hand during an incident and forgets to revert it. Lensix runs this check on a schedule across all your subscriptions, so a server that drifts out of compliance gets flagged regardless of how the change was made.

Tip: Pair the detective control (Lensix) with the preventive control (Azure Policy or CI gates). Prevention stops most issues at the door; detection catches the ones that slip through manual changes.


Best practices for PostgreSQL logging on Azure

  • Enable both log_connections and log_disconnections. One without the other gives you half a timeline.
  • Route logs to a durable destination. Configure diagnostic settings to send PostgreSQL logs to a Log Analytics workspace, Event Hub, or storage account, and set retention to match your compliance window.
  • Set log_retention_days appropriately on Single Server, or manage retention through your log destination on Flexible Server.
  • Tune log_min_duration_statement to capture slow queries without flooding your logs with every statement.
  • Alert on anomalies. Once disconnection data is flowing into Azure Monitor, build alerts for spikes in session terminations or unusually long-lived sessions.
  • Apply the setting fleet-wide through policy, not server by server. Manual configuration does not survive contact with a growing environment.

Disconnection logging is a small parameter with an outsized payoff. It costs almost nothing to enable, requires no downtime, and gives you the back half of every session timeline. When an audit or an incident shows up, you will be glad the data was already there.