Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Azure Postgres Flexible Server — Logs

Azure Database for PostgreSQL Flexible Server emits several resource log categories through Diagnostic Settings. Each category can be routed to a Log Analytics workspace, a Storage account, or Event Hubs.

There are two ways the data lands in Log Analytics:

  • Azure diagnostics mode — every category is flattened into the single AzureDiagnostics table. Category-specific fields are stored as dynamically typed columns with a type suffix (_s string, _d real/number, _t datetime, _b boolean). (This is the mode used by the my-la-workspace workspace that my-pg-prd-1 writes to.)
  • Resource-specific mode (recommended) — each category gets its own strongly typed table (e.g. PGSQLServerLogs), which is cheaper to query and store.

The field names below use the AzureDiagnostics form (with type suffixes), as observed live on my-pg-prd-1. In resource-specific tables the same fields exist without the suffix (e.g. errorLevel_sErrorLevel).


Log categories at a glance

CategoryDisplay nameWhat it isSourceSampling / collectionIngestion
PostgreSQLLogsPostgreSQL Server LogsNative Postgres server log streamPostgres log writerStreamed — every log line as written, no samplingFree
PostgreSQLFlexSessionsPostgreSQL Sessions dataSnapshot of active connections and their statepg_stat_activityFull snapshot every ~5 minPaid
PostgreSQLFlexQueryStoreRuntimeQuery Store RuntimePer-query execution statisticspg_stat_statementsCumulative delta read every 15 min ¹ — no executions lostPaid
PostgreSQLFlexQueryStoreWaitStatsQuery Store Wait StatisticsPer-query wait-event countspg_stat_activitypg_stat_activity sampled every ~1 sec; samples aggregated over 15 min ¹ windowsPaid
PostgreSQLQueryStoreSqlTextQuery Store SQL TextSQL text behind each query fingerprintQuery StoreCaptured once per new fingerprint — not periodicPaid
PostgreSQLFlexTableStatsAutovacuum & schema statisticsPer-table tuple counts and maintenance activitypg_stat_user_tablesFull snapshot every ~30 minPaid
PostgreSQLFlexDatabaseXactsRemaining transactionsPer-database XID/MXID wraparound headroompg_database system catalogFull snapshot every ~30 minPaid
PostgreSQLFlexPGBouncerPgBouncer LogsPgBouncer connection-pooler log streamPgBouncer log writerStreamed — every log line as written, no samplingPaid

¹ Configurable via server parameter pg_qs.interval_length_minutes (default 15).


Common envelope fields

These Azure Monitor fields are present on every category (not repeated in subpages).

Identity / routing

  • TimeGenerated (datetime) — when the record was ingested by Azure Monitor.
  • Category (string) — the log category (one of the values above).
  • OperationName (string) — always LogEvent for these logs.
  • LogicalServerName_s (string) — the Flexible Server name (e.g. my-pg-prd-1).
  • ReplicaRole_s (string)Primary or Replica.

Azure Resource Manager context

  • ResourceId / _ResourceId (string) — full ARM ID of the server.
  • Resource (string) — short resource name (upper-cased).
  • ResourceGroup, SubscriptionId, ResourceProvider (MICROSOFT.DBFORPOSTGRESQL), ResourceType (FLEXIBLESERVERS).
  • location_s (string) — Azure region (e.g. francecentral).

Plumbing

  • TenantId (string) — Log Analytics workspace ID.
  • SourceSystem (string) — always Azure.
  • Type (string) — table name (AzureDiagnostics).

Querying notes

  • Filter by server with LogicalServerName_s == "my-pg-prd-1" — the my-la-workspace workspace is shared by many servers.
  • Join Query Store data on the string fingerprint, not the numeric one — the _d float loses precision on 64-bit integers:
    AzureDiagnostics
    | where Category == "PostgreSQLFlexQueryStoreRuntime"
    | join kind=leftouter (
        AzureDiagnostics
        | where Category == "PostgreSQLQueryStoreSqlText"
        | distinct Queryid_str_s, Query_sql_text_s
      ) on Queryid_str_s
    
  • PostgreSQLLogs is the only category with free Log Analytics ingestion; all others are billed per GB of data ingested into the workspace.

Fields verified live (2026-06-23) against the my-la-workspace Log Analytics workspace, which collects diagnostics for my-pg-prd-1 and sibling Flexible Servers, in AzureDiagnostics mode.


General Q&A

Q&A

Q: Is pg_stat_activity data kept in Postgres over time, or is it sampled here and then discarded?

pg_stat_activity is a live, in-memory view — it shows the state of every backend process at the exact moment you query it, and nothing more. Postgres does not persist it, log it, or keep any history of it. The moment a session ends or a query finishes, its row is gone from the view.

You query pg_stat_activity
        │
        ▼
Postgres reads live state from shared memory → returns current rows
        │
One second later the same query returns entirely different rows.
No record of what was there before.

What Azure does is periodically sample that live view and ship the results to Log Analytics, which is what gives you historical data. Log Analytics retains those rows according to the workspace retention policy (default 30 days, configurable up to 730 days).

Postgres server                        Azure Log Analytics
─────────────────                      ───────────────────
pg_stat_activity  ──(sample every 5min)──▶  AzureDiagnostics
  (live, no history)                        (historical, retained)

pg_stat_statements and Query Store data are persisted on the server itself (in the azure_sys database), but it is still Azure's diagnostic pipeline that ships them to Log Analytics for historical querying.


Q: Since sampling is done every 5 minutes, does that mean a lot of pg_stat_statements content is never logged?

No — but the answer depends on the category. Each one collects data differently.

pg_stat_activity is a live view — you either catch a session in the snapshot or miss it. The 5-minute cadence of PostgreSQLFlexSessions loses a lot: any session that connects, runs, and disconnects between two snapshots is invisible.

pg_stat_statements is a cumulative accumulator. Every time any query finishes, Postgres atomically adds its stats to the running counters — regardless of whether any agent is watching. Azure reads the delta at the end of each 15-minute window. Calls_d = 10,000 means exactly 10,000 executions happened — none are missed.

Query executes and finishes
        │
        ▼
pg_stat_statements counters for this Queryid:
  calls     += 1
  total_time += <duration>
  rows       += <rows>
  blks_hit   += <hits>
  …  (atomic, on every execution, no monitoring agent needed)

every 15 min:
  Query Store reads delta → stores in azure_sys (no loss)
  Azure ships azure_sys  → Log Analytics     (no loss)

Summary across all categories:

Q: What does "Log Analytics ingestion" cost mean, and when do I actually get charged?

When you configure a Diagnostic Setting on the Postgres Flexible Server and point it at a Log Analytics workspace, Azure streams the enabled log categories into that workspace. Log Analytics charges for the data it receives — this is the ingestion cost, billed per GB of raw log data that flows in.

You pay when all three of these are true simultaneously:

  1. A Diagnostic Setting exists on the server pointing to a Log Analytics workspace.
  2. The paid category is enabled in that setting (e.g. PostgreSQLFlexSessions is checked).
  3. The server is actually producing data for that category (e.g. there are active sessions to snapshot).

If any one of the three is false — no setting, category disabled, or no data generated — you pay nothing for that category.

PostgreSQLLogs is a special exception: Microsoft made it free at the ingestion level because it is the basic operational log every server needs. All other categories incur the standard Log Analytics ingestion rate (~$2–3 per GB depending on region and commitment tier, with the first 5 GB/month per billing account free).

Retention is a separate charge: the first 30 days in a Log Analytics workspace are included; beyond that, you pay per GB per month for extended retention.

Diagnostic Setting enabled
        │
        ▼
Data flows to Log Analytics workspace
        │
        ▼
Ingestion billed per GB  (except PostgreSQLLogs → free)
        │
        ▼
Retention billed per GB/month after 30 days

In practice the biggest cost driver is PostgreSQLFlexQueryStoreRuntime and PostgreSQLFlexSessions on a busy server — they produce the most volume. PostgreSQLFlexDatabaseXacts and PostgreSQLFlexPGBouncer tend to be very small.


CategoryUnderlying sourceCollection mechanismLoses executions?
PostgreSQLFlexSessionspg_stat_activityPoint-in-time snapshot every ~5 minYes — only sessions alive at snapshot time
PostgreSQLFlexQueryStoreRuntimepg_stat_statementsWindowed delta every 15 minNo — every execution is counted
PostgreSQLFlexQueryStoreWaitStatsSampled pg_stat_activity (1-sec sampler)Wait-event samples aggregated every 15 minPartially — short waits between samples are missed
PostgreSQLLogsPostgres log streamEvery log line shipped as writtenNo — stream, not a snapshot
PostgreSQLFlexTableStatspg_stat_user_tablesSnapshot every collection intervalNo — cumulative counters
PostgreSQLFlexDatabaseXactspg_database system catalogSnapshot every collection intervalNo — current state
PostgreSQLFlexPGBouncerPgBouncer log streamEvery log line as writtenNo — stream