# Azure Duplicate Flow Logging

> Flags NSG flow logs that record traffic an unfiltered VNet flow log already captures for every network the NSG governs.

Source: https://zop.dev/integrations/azure/recommendations/azure-duplicate-flow-logging

---

## Paying twice for the same packets

Network Watcher has two flow logging models. NSG flow logs attach to a network security group;
virtual network flow logs attach to a whole network, subnet or NIC. Microsoft's
[VNet flow logs overview](https://learn.microsoft.com/en-us/azure/network-watcher/vnet-flow-logs-overview)
recommends disabling NSG flow logs before enabling VNet flow logs on the same workloads, to avoid
duplicate traffic recording and additional costs. Both kinds are billed per GB collected after the
first 5 GB each month, per the [Network Watcher pricing page](https://azure.microsoft.com/en-us/pricing/details/network-watcher/),
and traffic analytics adds a per-GB processing charge on top.

NSG flow logs are also on their way out: Microsoft
[retires them on September 30, 2027](https://learn.microsoft.com/en-us/azure/network-watcher/nsg-flow-logs-overview)
and no longer allows new ones to be created. An NSG log left running beside a newer VNet log is
pure overlap.

## Finding overlapping logs

List the flow logs in a region with their targets. NSG logs point at a `networkSecurityGroups`
resource; VNet logs point at a `virtualNetworks` resource:

```bash
az network watcher flow-log list --location <region> \
  --query "[].{name:name, enabled:enabled, target:targetResourceId}" -o table

az network nsg show --resource-group <rg> --name <nsg> \
  --query "{subnets:subnets[].id, nics:networkInterfaces[].id}"
```

If every subnet the NSG protects lives in a network that already has an enabled VNet flow log, the
NSG log is redundant.

## Three proofs before recommending a deletion

- **Every network is covered.** An NSG can protect subnets in more than one virtual network. Each
  one must have its own enabled VNet flow log; covering the first is not enough.
- **The covering log is unfiltered.** VNet flow logs can take filtering criteria that record only
  matching flows. A filtered log is not full coverage, and a log whose filter state is unknown does
  not count either.
- **No NIC binding.** If the NSG is attached to a network interface as well as subnets, that traffic
  is not accounted for by the network-level match, and the finding is withheld.

The NSG flow log itself must be enabled and must have a positive price.

## Cases left alone

A disabled NSG flow log, an NSG with no known networks, or any coverage gap on a single network
produces no finding. The goal is to never recommend deleting the only record of some traffic.
Gateway subnet logs are a separate case, covered by
<a href="https://zop.dev/integrations/azure/recommendations/azure-flow-log-on-a-gateway-subnet">Azure Flow Log on a Gateway Subnet</a>.

## The NSG flow log cost that disappears

```text
saving = full monthly cost of the redundant NSG flow log
cost after fix = 0
```

Deleting the duplicate stops its collection, storage and analytics meters together.

## Retiring the duplicate NSG flow log

1. Confirm the covering VNet flow log is healthy and its data is arriving in the destination storage
   account.
2. If traffic analytics ran on the NSG flow log, enable it on the VNet flow log too.
3. Delete the NSG flow log:
   `az network watcher flow-log delete --location <region> --name <flow-log>`.
4. Check for further NSG logs on the same workloads; one can exist at both the subnet and the NIC
   level.
