# Azure PostgreSQL Server Idle

> Flags PostgreSQL Flexible Servers with no connections and CPU under 1% for 30 days that still bill for compute and storage.

Source: https://zop.dev/integrations/azure/recommendations/azure-postgresql-server-idle

---

## A database nobody connects to still pays for its vCores

A Flexible Server bills for the compute tier it runs on and for provisioned storage. The
[service overview](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/overview)
describes stop and start as the way to lower cost on demand: compute billing stops immediately
when the server is stopped. But a stopped server stays stopped only for seven days before it
starts again, and Microsoft's description covers compute only, not the storage you provisioned.

So stopping is a pause for dev and test schedules, not a fix for a server nobody uses. For that,
the full saving comes from deleting it.

## Measuring connections and CPU on a server

```bash
az postgres flexible-server list \
  --query "[].{name:name, rg:resourceGroup, sku:sku.name, tier:sku.tier, state:state}" -o table

az monitor metrics list --resource <server-resource-id> \
  --metric active_connections cpu_percent --offset 30d --interval PT24H --aggregation Average Maximum
```

## Both connections and CPU have to be flat

1. The active connections series and the CPU percent series are both present.
2. Each covers at least 30 days.
3. Active connections are below 1 on both average and peak.
4. CPU percent is below 1 on both average and peak. CPU is a second hard gate, not a tiebreaker:
   a server running scheduled jobs from inside, with no client connection, is still in use.
5. The server has a known monthly cost above zero.

## Servers that stay off the list

A single connection or any CPU work above the 1% floor clears the server. Missing metrics, or less
than 30 days of them, also mean no finding. A hand-written connection tag that some earlier logic
trusted is no longer read; only Azure Monitor data counts.

This is an advisory finding. ZopNight does not stop the server for you, because a stop would not
deliver the saving shown and the server would restart itself after seven days anyway.

## Saving from deleting the server

```text
saving = current monthly cost of the server (compute plus storage)
cost after fix = 0
```

## Retiring an idle PostgreSQL server

1. Confirm with the owning team that no application, report or pipeline uses it, and check its
   firewall rules and private endpoints for hints about former clients.
2. Take a final dump with `pg_dump` if the data may be needed later; do not rely on the server's
   automated backups outliving it.
3. Delete it: `az postgres flexible-server delete --resource-group my-rg --name my-pg --yes`.
4. If it is needed a few days a month, use `az postgres flexible-server stop` between uses and plan
   for the seven-day automatic restart.

**Warning**
Deleting the server deletes its databases. Export anything you need first.
