Azure Database for PostgreSQL flexible server — Entra authentication, roles for managed identities, private access or private endpoints, versions and extended support, errors
Running PostgreSQL flexible server without passwords — authConfig for Entra only, Entra admins, pgaadauth_create_principal for apps and groups, tokens as passwords from Node.js pg, the two exclusive network modes (VNet integration with a delegated /28+ subnet and a .postgres.database.azure.com zone, or public access plus private endpoints), the automatic paid extended support for 11–13 since August 2026 and 14 from February 2027, and the login errors.
markdownreferencev1F35G-1NEWstage: buildtrust: officialservice: postgresqlinterface: iacinterface: cliinterface: sdkAzure Database for PostgreSQL flexible server Entra authenticationauthConfig activeDirectoryAuth passwordAuthMicrosoft Entra authentication only PostgreSQLaz postgres flexible-server microsoft-entra-admin create--microsoft-entra-auth--password-authflexibleServers/administratorspgaadauth_create_principalpgaadauth_create_principal_with_oidazure_pg_adminhttps://ossrdbms-aad.database.windows.net/.defaultoss-rdbms tokentoken as password 5 to 60 minutesNode pg password functionEntra group sync 30 minutesVNet integration delegated subnet Microsoft.DBforPostgreSQL/flexibleServersprivate DNS zone .postgres.database.azure.comprivatelink.postgres.database.azure.comprivate endpoint not supported VNet integrationAzureActiveDirectory service tagPostgreSQL extended supportPostgreSQL 11 12 13 extended support August 1 2026PostgreSQL 14 standard support end January 31 2027PostgreSQL 18FATAL: password authentication failed for userno pg_hba.conf entry for hostPGSSLMODE requireMicrosoft.DBforPostgreSQL/flexibleServers@2025-08-01
PostgreSQL flexible server
Entra authentication
authConfig:activeDirectoryAuth: 'Enabled'andpasswordAuth: 'Disabled'for Entra only (CLI--microsoft-entra-auth Enabled --password-auth Disabled; the CLI defaults are the reverse). Enable it at creation or later.- Entra admins (users, groups, service principals or managed identities): one at provisioning, more afterwards; the resource is
flexibleServers/administrators/<objectId>(az postgres flexible-server microsoft-entra-admin create -g <rg> -s <server> --display-name <name> --object-id <id> --type Group). Don't run the app as the admin: it hasCREATEDBand elevated rights. - App roles: connected as an Entra admin to the
postgresdatabase:
SELECT * FROM pgaadauth_create_principal('<managed identity display name>', false, false);
-- or, when display names collide:
SELECT * FROM pgaadauth_create_principal_with_oid('<role name>', '<object id>', 'service', false, false);
GRANT CONNECT ON DATABASE appdb TO "<managed identity display name>";
Arguments: role name (UPN for users, display name for groups and service principals), isAdmin, isMfa. A role linked to a group lets every member sign in with the group's role name; group membership syncs every 30 minutes.
- Tokens are the password: scope
https://ossrdbms-aad.database.windows.net/.default(CLI:az account get-access-token--resource-type oss-rdbms), valid 5–60 minutes, checked at sign-in. Microsoft says that from January 2027 tokens for audiences other thanossrdbmswon't be accepted. - With private access, allow outbound to the
AzureActiveDirectoryservice tag, and keeplogin.microsoftonline.comandgraph.microsoft.comresolving publicly, or admin assignment and sign-in fail.
Network: pick one mode at creation
| Private access (VNet integration) | Public access (+ private endpoints) | |
|---|---|---|
| Placement | A subnet delegated to Microsoft.DBforPostgreSQL/flexibleServers, only for these servers, /28 or larger (an HA server uses 4 addresses) | No subnet; firewall rules (none = no access) and/or private endpoints (groupId postgresqlServer, zone privatelink.postgres.database.azure.com) |
| DNS | A private zone whose name ends in .postgres.database.azure.com and isn't the server's name | Private endpoint zone group |
| Constraints | Can't move to another VNet or subnet; subnet can't grow once used; no private endpoints; don't force all Storage traffic through an NVA | CLI --public-access 0.0.0.0 admits all Azure services |
Versions
18 down to 11 are offered. 11, 12 and 13 have been in paid extended support since August 1, 2026 (billing from September 1, 2026; ends March 31, 2027, November 13, 2027 and November 12, 2028). 14's standard support ends January 31, 2027. Enrolment is automatic and charged only while a server runs; upgrade the major version to leave it.
Bicep (Entra only, private access)
// PostgreSQL flexible server: Microsoft Entra only, private (VNet-integrated), with an Entra admin group
param location string = resourceGroup().location
param serverName string
param delegatedSubnetId string // subnet delegated to Microsoft.DBforPostgreSQL/flexibleServers, /28 or larger
param privateDnsZoneId string // a zone ending in .postgres.database.azure.com, linked to the VNet
param adminGroupName string
param adminGroupObjectId string
resource pg 'Microsoft.DBforPostgreSQL/flexibleServers@2025-08-01' = {
name: serverName
location: location
sku: {
name: 'Standard_D4ds_v5'
tier: 'GeneralPurpose'
}
properties: {
version: '17'
authConfig: {
activeDirectoryAuth: 'Enabled'
passwordAuth: 'Disabled' // Entra only; the hub's reading is that no administratorLogin is then needed
tenantId: tenant().tenantId
}
network: {
delegatedSubnetResourceId: delegatedSubnetId
privateDnsZoneArmResourceId: privateDnsZoneId
}
storage: {
storageSizeGB: 64
autoGrow: 'Enabled'
}
highAvailability: {
mode: 'ZoneRedundant'
}
}
}
resource entraAdmin 'Microsoft.DBforPostgreSQL/flexibleServers/administrators@2025-08-01' = {
parent: pg
name: adminGroupObjectId
properties: {
principalType: 'Group'
principalName: adminGroupName
tenantId: tenant().tenantId
}
}
Node.js
import pg from "pg";
import { DefaultAzureCredential } from "@azure/identity";
const credential = new DefaultAzureCredential();
const SCOPE = "https://ossrdbms-aad.database.windows.net/.default"; // PostgreSQL and MySQL flexible servers
// The role must exist: SELECT * FROM pgaadauth_create_principal('<identity display name>', false, false);
export const pool = new pg.Pool({
host: `${process.env.PG_SERVER}.postgres.database.azure.com`,
database: "appdb",
user: process.env.PG_USER ?? "", // the role name: UPN for users, display name for groups and identities
// A function, so every new pooled connection gets a fresh token (tokens last 5–60 minutes)
password: async () => (await credential.getToken(SCOPE)).token,
ssl: { rejectUnauthorized: true },
max: 10,
idleTimeoutMillis: 30_000,
});
export async function main(): Promise<void> {
const { rows } = await pool.query<{ now: Date }>("SELECT now() AS now");
console.log(rows[0]?.now);
await pool.end();
}
Read replicas, major version upgrades and elastic clusters: reference/postgresql/replicas-upgrades-and-clusters.md. Retired database services: reference/databases/retired-and-replacements.md.
Errors
| Message | Cause → fix |
|---|---|
FATAL: password authentication failed for user "<user-name>" | Wrong password; for Entra: expired or wrong-audience token, a user name that doesn't match the role exactly (case-sensitive), or no pgaadauth_create_principal role |
FATAL: no pg_hba.conf entry for host "y.y.y.y", user "<user-name>", database "postgres", no encryption (right after the first error) | libpq retried without TLS after the TLS attempt failed: set PGSSLMODE=require (or ssl in the client) so you see the real error |
| Deployment fails naming the private DNS zone | The zone name equals the server name, or the zone's subscription lacks the Microsoft.DBforPostgreSQL provider registration |
| Timeouts from inside the VNet | The hub's reading: an NSG or UDR on the delegated subnet, or DNS not resolving through the linked zone (guides/networking/diagnose-connectivity.md) |