Microsoft Defender for Cloud · Azure Database for PostgreSQL
Geo-redundant backup should be enabled for Azure Database for PostgreSQL
Written and reviewed by Emnode · Last reviewed
What does the recommendation "Geo-redundant backup should be enabled for Azure Database for PostgreSQL" check?
Flags any Azure Database for PostgreSQL Single Server whose backup storage redundancy is set to locally redundant rather than geo-redundant, so its automated backups live only in the server's own region. It reads the server's 'geoRedundantBackup' property and audits the create-time choice; it does not cover the newer Flexible Server deployment model, which has its own separate recommendation, and it says nothing about backup retention length, point-in-time restore being configured, or whether you have ever tested a restore.
Why does "Geo-redundant backup should be enabled for Azure Database for PostgreSQL" matter?
With locally redundant backups, a regional outage or a paired-region disaster takes your backups offline at the same moment as the live database, leaving no copy to restore from and no geo-restore path to a paired region. For a system of record holding customer or financial data, that turns a regional incident into permanent data loss and a breached recovery point objective, which can mean regulatory exposure and a failed audit on top of the outage itself. Geo-redundant backup replicates each backup to the Azure paired region, so you can geo-restore into a healthy region while the primary is still down, which is the difference between hours of controlled failover and an unrecoverable outage. The cost is modest relative to the storage you already pay for, and for any tier that supports it there is rarely a good reason to leave production data locally redundant.
How do I fix "Geo-redundant backup should be enabled for Azure Database for PostgreSQL"?
- Because backup redundancy can only be chosen when the server is created and cannot be switched afterwards, provision a replacement Single Server with geo-redundancy on: 'az postgres server create -g <rg> -n <server> --geo-redundant-backup Enabled --sku-name GP_Gen5_2', then migrate data across (geo-redundant backup requires the General Purpose or Memory Optimized tier).
- In Bicep or an ARM template, set the server's 'properties.storageProfile.geoRedundantBackup' to 'Enabled' so every new environment is provisioned correctly and nobody has to remember the flag.
- Enforce it at scale by assigning the built-in audit policy, looked up by its exact display name so no GUID is hardcoded: 'pid=$(az policy definition list --query "[?displayName=='\''Geo-redundant backup should be enabled for Azure Database for PostgreSQL'\''].name" -o tsv)' then 'az policy assignment create --name pg-geo-backup --policy "$pid" --scope <subscription-or-rg-id>'.
Remediation script · bash
# 1. Lock the wire and the network on a production PostgreSQL flexible server.
RG=db-prod-rg
SRV=ordersprod-pg
# Enforce encrypted connections (dynamic, no restart needed).
az postgres flexible-server parameter set \
--resource-group "$RG" --server-name "$SRV" \
--source user-override \
--name require_secure_transport --value ON
# Pin the minimum TLS version.
az postgres flexible-server parameter set \
--resource-group "$RG" --server-name "$SRV" \
--source user-override \
--name ssl_min_protocol_version --value TLSv1.2
# Disable public network access.
az postgres flexible-server update \
--resource-group "$RG" --name "$SRV" \
--public-access Disabled
# 2. Turn on the pgaudit trail and connection throttling.
for p in "pgaudit.log=role,ddl,misc" \
"pgaudit.log_client=ON" \
"pgaudit.log_level=log" \
"pgaudit.log_statement=on" \
"pgaudit.log_statement_once=on" \
"connection_throttle.enable=on"; do
az postgres flexible-server parameter set \
--resource-group "$RG" --server-name "$SRV" \
--source user-override \
--name "${p%%=*}" --value "${p#*=}"
done
# 3. Provision a Microsoft Entra administrator and disable password sign-in.
az postgres flexible-server ad-admin create \
--resource-group "$RG" --server-name "$SRV" \
--display-name "dba-team" \
--object-id "$(az ad group show --group dba-team --query id -o tsv)" \
--type Group
az postgres flexible-server update \
--resource-group "$RG" --name "$SRV" \
--microsoft-entra-auth Enabled --password-auth Disabled
# 4. Ratchet it shut: deny any future PostgreSQL flexible server with public access.
# Look the built-in policy up by its EXACT display name, never paste a guessed GUID.
PID=$(az policy definition list \
--query "[?displayName=='Public network access should be disabled for PostgreSQL flexible servers'].name" \
-o tsv)
az policy assignment create \
--name deny-public-pg-flex \
--policy "$PID" \
--params '{"effect":{"value":"Deny"}}' \
--scope "/subscriptions/00000000-0000-0000-0000-000000000000" Full walkthrough (console steps, edge cases and verification) in the lesson Harden Azure MySQL and PostgreSQL.
Is "Geo-redundant backup should be enabled for Azure Database for PostgreSQL" a false positive?
A non-production or transient PostgreSQL Single Server, such as a throwaway test instance or a copy seeded purely from data you can regenerate, will flag even though geo-redundant backup buys you nothing there and only adds storage cost. Confirm the database holds no system-of-record data, then exempt that server from the assignment rather than rebuilding it. Note also that PostgreSQL Single Server is on a retirement path, so the durable fix for a production workload is to move to Flexible Server, which supports geo-redundant backup under its own recommendation.
More Azure Database for PostgreSQL controls
- (Enable if required) PostgreSQL servers should use customer-managed keys to encrypt data at rest
- Azure Database for PostgreSQL should have a Microsoft Entra administrator provisioned
- Enforce SSL connection should be enabled for PostgreSQL database servers
- Private endpoint should be enabled for PostgreSQL servers
- Public network access should be disabled for PostgreSQL servers