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
AzureDiagnosticstable. Category-specific fields are stored as dynamically typed columns with a type suffix (_sstring,_dreal/number,_tdatetime,_bboolean). (This is the mode used by themy-la-workspaceworkspace thatmy-pg-prd-1writes 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
AzureDiagnosticsform (with type suffixes), as observed live onmy-pg-prd-1. In resource-specific tables the same fields exist without the suffix (e.g.errorLevel_s→ErrorLevel).
Log categories at a glance
| Category | Display name | What it is | Source | Sampling / collection | Ingestion |
|---|---|---|---|---|---|
PostgreSQLLogs | PostgreSQL Server Logs | Native Postgres server log stream | Postgres log writer | Streamed — every log line as written, no sampling | Free |
PostgreSQLFlexSessions | PostgreSQL Sessions data | Snapshot of active connections and their state | pg_stat_activity | Full snapshot every ~5 min | Paid |
PostgreSQLFlexQueryStoreRuntime | Query Store Runtime | Per-query execution statistics | pg_stat_statements | Cumulative delta read every 15 min ¹ — no executions lost | Paid |
PostgreSQLFlexQueryStoreWaitStats | Query Store Wait Statistics | Per-query wait-event counts | pg_stat_activity | pg_stat_activity sampled every ~1 sec; samples aggregated over 15 min ¹ windows | Paid |
PostgreSQLQueryStoreSqlText | Query Store SQL Text | SQL text behind each query fingerprint | Query Store | Captured once per new fingerprint — not periodic | Paid |
PostgreSQLFlexTableStats | Autovacuum & schema statistics | Per-table tuple counts and maintenance activity | pg_stat_user_tables | Full snapshot every ~30 min | Paid |
PostgreSQLFlexDatabaseXacts | Remaining transactions | Per-database XID/MXID wraparound headroom | pg_database system catalog | Full snapshot every ~30 min | Paid |
PostgreSQLFlexPGBouncer | PgBouncer Logs | PgBouncer connection-pooler log stream | PgBouncer log writer | Streamed — every log line as written, no sampling | Paid |
¹ 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) — alwaysLogEventfor these logs.LogicalServerName_s(string) — the Flexible Server name (e.g.my-pg-prd-1).ReplicaRole_s(string) —PrimaryorReplica.
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) — alwaysAzure.Type(string) — table name (AzureDiagnostics).
Querying notes
- Filter by server with
LogicalServerName_s == "my-pg-prd-1"— themy-la-workspaceworkspace is shared by many servers. - Join Query Store data on the string fingerprint, not the numeric one — the
_dfloat 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 PostgreSQLLogsis 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-workspaceLog Analytics workspace, which collects diagnostics formy-pg-prd-1and sibling Flexible Servers, inAzureDiagnosticsmode.
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:
- A Diagnostic Setting exists on the server pointing to a Log Analytics workspace.
- The paid category is enabled in that setting (e.g.
PostgreSQLFlexSessionsis checked). - 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.
| Category | Underlying source | Collection mechanism | Loses executions? |
|---|---|---|---|
PostgreSQLFlexSessions | pg_stat_activity | Point-in-time snapshot every ~5 min | Yes — only sessions alive at snapshot time |
PostgreSQLFlexQueryStoreRuntime | pg_stat_statements | Windowed delta every 15 min | No — every execution is counted |
PostgreSQLFlexQueryStoreWaitStats | Sampled pg_stat_activity (1-sec sampler) | Wait-event samples aggregated every 15 min | Partially — short waits between samples are missed |
PostgreSQLLogs | Postgres log stream | Every log line shipped as written | No — stream, not a snapshot |
PostgreSQLFlexTableStats | pg_stat_user_tables | Snapshot every collection interval | No — cumulative counters |
PostgreSQLFlexDatabaseXacts | pg_database system catalog | Snapshot every collection interval | No — current state |
PostgreSQLFlexPGBouncer | PgBouncer log stream | Every log line as written | No — stream |