This check flags Azure Database for PostgreSQL servers configured with locally redundant backups instead of geo-redundant ones. Without geo-redundancy, a regional Azure outage can leave you unable to restore your database. The fix is to enable geo-redundant backups, which on Flexible Server must be set at creation time.
Backups feel like a solved problem until the day you actually need one and it is not where you expect it to be. Azure Database for PostgreSQL takes automated backups out of the box, but the default redundancy setting keeps those backups inside a single region. If that region goes down, your backups go down with it. The postgresql_nogeoreplication check looks for exactly this gap.
This post walks through what the check detects, why locally redundant backups are a real liability, and how to enable geo-redundancy across both deployment models, the CLI, and Terraform.
What this check detects
The check inspects each Azure Database for PostgreSQL server in your subscription and reports any server where geo-redundant backup storage is not enabled. In practice that means the server is using locally redundant backup storage, which keeps three synchronous copies of your backup data, but all of them live in the primary region.
Geo-redundant backup storage adds a fourth layer: it asynchronously replicates your backups to the Azure paired region hundreds of miles away. With it enabled, you can run a geo-restore into the paired region even when the primary region is completely unavailable.
Note: Azure offers PostgreSQL in two deployment models, Single Server (being retired) and Flexible Server. The backup redundancy setting exists in both, but the way you configure it differs significantly. The most important difference: on Flexible Server, geo-redundant backup can only be chosen when you create the server, not toggled on later.
Why it matters
Locally redundant backups protect you against hardware failure, a corrupted disk, an accidental DROP TABLE, or a bad migration. They do not protect you against the loss of an entire region. Regional outages are rare, but they happen, and when they do they tend to take everything in that region down at once, including your nice triple-replicated local backups.
Here is the scenario that bites teams:
- Your production PostgreSQL server runs in a single region with locally redundant backups.
- That region experiences an extended outage or, in the worst case, a disaster.
- Your application is offline, and so is every copy of your backup data.
- You have no way to restore into a healthy region because no backup ever left the failed one.
For anything that carries an RTO or RPO commitment, or any workload covered by a compliance framework that requires disaster recovery, locally redundant backups quietly fail the assignment. Auditors under SOC 2, ISO 27001, and similar frameworks routinely ask how you would recover from a regional failure. "We can't" is not a good answer.
Warning: Geo-redundant backup storage roughly doubles your backup storage cost compared to locally redundant storage, since you are now paying to store and replicate a second copy in the paired region. For most production databases this is trivial next to the cost of an unrecoverable outage, but it is worth budgeting for.
How to fix it
The remediation path depends entirely on which deployment model you are on and, for Flexible Server, whether the server already exists.
Flexible Server: set it at creation time
On Flexible Server, geo-redundancy is a create-time decision. Pass --geo-redundant-backup Enabled when provisioning the server:
az postgres flexible-server create \
--resource-group my-rg \
--name my-pg-server \
--location eastus \
--tier GeneralPurpose \
--sku-name Standard_D2ds_v4 \
--storage-size 128 \
--geo-redundant-backup Enabled \
--admin-user pgadmin \
--admin-password ''
If your server already exists with locally redundant backups, you cannot flip the setting in place. You need to migrate to a new server that has geo-redundancy enabled. The cleanest approach is a point-in-time restore into a fresh server created with the flag set:
Danger: The commands below create new resources and, in the cutover step, point your application at a different server. Test the restored server thoroughly before switching production traffic, and keep the original server running until you have validated the new one. Plan for a maintenance window since a cutover means connection strings change.
# Restore the existing server into a new geo-redundant server
az postgres flexible-server restore \
--resource-group my-rg \
--name my-pg-server-geo \
--source-server my-pg-server \
--geo-redundant-backup Enabled
After the restore completes, validate the data, update your application connection strings to the new server, then decommission the old one once you are confident.
Single Server: update in place
On Single Server, geo-redundant backup is also a create-time setting and cannot be changed afterward. If you are still running Single Server, the recommended path is to migrate to Flexible Server with geo-redundancy enabled, since Single Server is on a retirement timeline.
Note: Azure has announced the retirement of Single Server for PostgreSQL. If this check flags a Single Server instance, treat it as a prompt to plan your migration to Flexible Server rather than trying to patch the backup setting on a platform that is going away.
Console steps for a new Flexible Server
- In the Azure portal, go to Create a resource and choose Azure Database for PostgreSQL Flexible Server.
- Fill in the basics: resource group, server name, region, and compute tier.
- Open the Backup section (or the Compute + storage blade).
- Under Geo-redundancy, select Enabled.
- Review and create.
Terraform
If you manage infrastructure as code, set geo_redundant_backup_enabled on the resource:
resource "azurerm_postgresql_flexible_server" "main" {
name = "my-pg-server"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
version = "16"
sku_name = "GP_Standard_D2ds_v4"
storage_mb = 131072
administrator_login = "pgadmin"
administrator_password = var.db_password
geo_redundant_backup_enabled = true
backup_retention_days = 14
}
Warning: Changing geo_redundant_backup_enabled on an existing azurerm_postgresql_flexible_server forces resource replacement in Terraform. Running terraform apply against a live database without a deliberate migration plan will destroy and recreate the server. Review the plan output carefully before applying.
How to prevent it from happening again
Because geo-redundancy has to be set at creation, the most effective control is to catch missing geo-redundancy before a server is ever provisioned. Build the guardrail into the place where databases get created.
Azure Policy
Use Azure Policy to audit or deny non-geo-redundant servers. Here is a policy rule that audits Flexible Servers where geo-redundant backup is not enabled:
{
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.DBforPostgreSQL/flexibleServers"
},
{
"field": "Microsoft.DBforPostgreSQL/flexibleServers/backup.geoRedundantBackup",
"notEquals": "Enabled"
}
]
},
"then": {
"effect": "audit"
}
}
Start with audit to find existing offenders without breaking deployments, then switch the effect to deny once your pipelines consistently set the flag.
Tip: Pair the policy with a remediation runbook. When the deny effect blocks a deployment, your error message should link straight to the documentation explaining that geo-redundancy is create-time only. That saves an engineer from filing a ticket trying to "just toggle it on."
CI/CD gates for IaC
If your Terraform or Bicep lives in version control, scan it before it merges. Tools like Checkov, tfsec, and Terrascan can fail a pull request when geo-redundancy is missing. A quick Checkov run in your pipeline:
checkov -d ./infra --framework terraform
You can also write a lightweight custom check that asserts geo_redundant_backup_enabled = true on every PostgreSQL resource, so a regression never makes it past review.
Continuous monitoring
Policy and CI gates cover new resources, but you still want ongoing visibility into drift and into anything created outside your standard process. Lensix runs the postgresql_nogeoreplication check across your subscriptions on a schedule, so a server that slips through manual provisioning shows up in your findings instead of waiting to surprise you during an incident.
Best practices
- Decide redundancy at design time. Because Flexible Server locks geo-redundancy at creation, treat it as part of your reference architecture, not an afterthought.
- Match backup retention to your recovery needs. Geo-redundancy answers "where," but
backup_retention_daysanswers "how far back." Set both deliberately. - Test your geo-restore. A backup you have never restored is a hypothesis, not a recovery plan. Run a geo-restore drill into the paired region at least once so you know the runbook works and you know how long it takes.
- Consider read replicas for active DR. Geo-redundant backup gives you recovery from a disaster, but a cross-region read replica can give you a faster failover and lower RPO if your workload demands it. The two are complementary.
- Document RTO and RPO per database. Tag each server with its recovery objectives so the right backup posture is obvious to whoever provisions or audits it.
- Plan the Single Server migration. If any flagged servers are Single Server, fold the geo-redundancy fix into your move to Flexible Server rather than treating them as separate projects.
Geo-redundant backups are cheap insurance against an expensive, rare event. The hard part is not the cost, it is remembering to set the flag before the server exists. Bake it into your templates, enforce it with policy, and let continuous scanning catch the stragglers.

