The component groups three Azure resources — server, database, and firewall rule — under a single
Pulumi parent. The credentials are generated internally so no sensitive values are passed by the
caller or stored in config.
Resource
Purpose
pulumi_random.RandomInteger
Generates a unique 8-digit suffix for the admin login
pulumi_random.RandomPassword
Generates a 16-character alphanumeric admin password
azure_native.dbforpostgresql.Server
The Flexible Server instance
azure_native.dbforpostgresql.Database
The application database inside the server
azure_native.dbforpostgresql.FirewallRule
Allows connections from the AKS node subnet
get_npgsql_connection_string builds the connection string only after a database is created,
combining four Output values — FQDN, database name, login, and password — into a single secret
Output[str] in Npgsql format.
SSL Mode=Require
Npgsql’s SSL Mode=Require encrypts the connection without verifying the server certificate. No
CA certificate needs to be installed on the app side — Azure PostgreSQL Flexible Server handles TLS
termination transparently.
Step 2 — Wire the component into __main__.py
Add the import at the top of __main__.py:
from postgres_flexible_server import PostgresFlexibleServer
Then add the following block inside main(), after the Kubernetes and DNS setup, before the
exports:
pg = PostgresFlexibleServer(f"pg-{suffix}")
db = pg.add_database("app")
pg.add_firewall_rule("aks-egress", aks.egress_ip.ip_address, aks.egress_ip.ip_address)
The component provisions its own Resource Group (rg-pg-{suffix}), keeping the PostgreSQL
lifecycle independent from the rest of the stack. The firewall rule covers the AKS egress IP so
app pods can reach the server.
The connection string is exported as a secret stack output. Pulumi encrypts it in state and
pulumi stack output will not display it unless --show-secrets is passed.
Regional quota
PostgreSQL Flexible Server is not available in all Azure regions by default. If pulumi up fails
with LocationIsOfferRestricted, request a quota increase for your target region:
aka.ms/postgres-request-quota-increase
Step 3 — Deploy
pulumi up
The first deployment provisions the server, which typically takes 5–10 minutes. Subsequent updates
are fast unless the server itself changes.
Explanation
PostgreSQL Flexible Server is a managed service — Azure handles the VM, OS patches, and high
availability. You declare what you want (version, SKU, storage); Azure figures out where and how to
run it.
Step 4 — Patch deployment.yaml with the connection string
Add the POSTGRES_CONNECTION_STRING env var to the container spec in deployment.yaml:
envsubst substitutes ${POSTGRES_CONNECTION_STRING} in the YAML with the exported shell
variable before the manifest reaches kubectl. The connection string never has to be typed or
copy-pasted manually.
The app checks for POSTGRES_CONNECTION_STRING at startup. When the env var is present it opens
an NpgsqlConnection instead of SqliteConnection and runs the PostgreSQL schema migration.
Messages submitted after the switch are stored in the managed database and survive pod restarts.
Inspect the application log
While the port-forward is running and you browse to http://localhost:8080, stream the live
application log in a second terminal: