Back to blog
Azure CloudOct 27, 20254 min read

Deploying Azure PostgreSQL Flexible Server with Terraform/OpenTofu — Private DNS, Subnet Delegation, and Lifecycle Control

Deploying Azure PostgreSQL Flexible Server with Terraform/OpenTofu — Private DNS, Subnet Delegation, and Lifecycle Control

In this post, we’ll explore how to deploy Azure PostgreSQL Terraform, using Private DNS, subnet delegation, and full lifecycle control.

Databases are the heart of every cloud deployment. While compute instances can spin up and down in seconds, your data layer demands stability, privacy, and precision. In Azure, that’s where PostgreSQL Flexible Server comes in — a fully managed database service that you can provision, secure, and connect privately using Terraform or OpenTofu. Let’s walk through a real example straight from my Multicloud Foundations training.

Step 1 — Deploying Azure PostgreSQL Terraform

Here’s a complete Terraform definition that creates a managed PostgreSQL instance in Azure.
You’ll notice a few important arguments that go beyond the basics:

resource "azurerm_postgresql_flexible_server" "foggykitchen_pg" {
  name                   = "foggykitchen-pg"
  resource_group_name    = azurerm_resource_group.foggykitchen_rg.name
  location               = azurerm_resource_group.foggykitchen_rg.location
  version                = "13"
  administrator_login    = var.pg_admin_username
  administrator_password = var.pg_admin_password
  storage_mb             = 32768
  sku_name               = "GP_Standard_D2s_v3"
  delegated_subnet_id    = azurerm_subnet.foggykitchen_db_subnet.id
  private_dns_zone_id    = azurerm_private_dns_zone.foggykitchen_pg_dns.id
  public_network_access_enabled = false
  maintenance_window {
    day_of_week  = 0
    start_hour   = 22
    start_minute = 0
  }
  lifecycle {
    ignore_changes = [
      zone
    ]
  }
  depends_on = [
    azurerm_private_dns_zone_virtual_network_link.foggykitchen_pg_dns_link
  ]
}

💡 Let’s break down the most interesting parts:

  • delegated_subnet_id – the database runs in a delegated subnet, meaning it has no public IP and relies entirely on your VNet.

  • private_dns_zone_id – this links the server to a private DNS zone, so applications can connect via foggykitchen-pg.postgres.database.azure.com internally.

  • public_network_access_enabled = false – this ensures your database never goes over the public Internet.

  • ignore_changes – prevents Terraform from trying to recreate the resource when Azure automatically assigns an availability zone.

This setup gives you an enterprise-grade database — fully private and fully automated.

Step 2 — Configuring Private DNS

To make private connections work, Terraform first needs to define a DNS zone and link it to your virtual network:

resource "azurerm_private_dns_zone" "foggykitchen_pg_dns" {
  name                = "privatelink.postgres.database.azure.com"
  resource_group_name = azurerm_resource_group.foggykitchen_rg.name
}
resource "azurerm_private_dns_zone_virtual_network_link" "foggykitchen_pg_dns_link" {
  name                  = "pg-dns-link"
  resource_group_name   = azurerm_resource_group.foggykitchen_rg.name
  private_dns_zone_name = azurerm_private_dns_zone.foggykitchen_pg_dns.name
  virtual_network_id    = azurerm_virtual_network.foggykitchen_vnet.id
}

This is where the magic happens.
Once this zone is linked, any VM inside the VNet can resolve the private PostgreSQL hostname — without exposing a single packet outside your network.

Step 3 — Creating a Database

After provisioning the Flexible Server, Terraform can immediately create databases on it:

resource "azurerm_postgresql_flexible_server_database" "foggykitchen_db" {
  name      = "foggydb"
  server_id = azurerm_postgresql_flexible_server.foggykitchen_pg.id
  collation = "en_US.utf8"
  charset   = "UTF8"
}

Simple, predictable, and fully automatable.
At this point, your backend VMs (for example foggykitchen_backend_vm1) can connect directly using private DNS — no firewall rules, no public endpoint, and no secrets exposed.

Step 4 — Putting It All Together

Here’s what the full architecture looks like:

Architecture diagram of Azure PostgreSQL Flexible Server deployed with Terraform/OpenTofu using Private DNS and delegated subnet.

🖼️ Figure 1. Azure PostgreSQL Flexible Server with Private DNS and Subnet Delegation.

Step 5 — Lifecycle and Maintenance

When managing databases as code, the lifecycle block in Terraform becomes your best friend.
Azure sometimes moves resources across zones or adjusts metadata during maintenance.
By ignoring those non-critical changes, you keep your deployments idempotent and your CI/CD pipelines smooth.

lifecycle {
  ignore_changes = [ zone ]
}

In production, this single line can save hours of troubleshooting.

FoggyKitchen Takeaway

At FoggyKitchen, we don’t just spin up managed databases — we cook them with precision.
From subnet delegation to DNS linking, every ingredient matters when you want a reliable, private, and reproducible data layer.

Azure’s abstractions make life easier, but Terraform ensures you stay in control.
And when you combine both, you get the best of both worlds: speed and transparency.

🎓 Explore More

👉 Multicloud Foundations: Azure & OCI deployed with Terraform/OpenTofu
Learn how this PostgreSQL database becomes part of a real multicloud topology — securely connected to Oracle Cloud workloads.

🔗 You might also like:

Multicloud Azure OCI Terraform architecture diagram

From Cloud Recipes to Real Automation

Learn how to connect Azure PostgreSQL and OCI workloads using Terraform/OpenTofu — securely, privately, and reproducibly.

Hands-on training that unifies Azure and OCI automation — compute, storage, networking, and databases — all in Terraform/OpenTofu.

👉 Explore Multicloud Foundations

🔒 Lifetime • ⏱️ Self-paced • 🧪 Real labs

Martin Linxfeld
Author

Martin Linxfeld

FoggyKitchen founder. Cloud automation, multicloud networking, Terraform, OpenTofu, and practical platform engineering.

Previous postConfiguring the OCI Provider in Terraform/OpenTofu: Cloud Shell, Resource Manager, Multi-Region, and Home Region Best PracticesNov 05, 2025Next post🧱 What Is Infrastructure as Code (IaC)? A Practical Look with TerraformOct 25, 2025

Leave a reply

Comments are part of the mockup. Authentication and moderation will be connected later.