Homeβ€Ί Blogβ€Ί Azure Architecture Series #84 β€” Azure Firewall: SKUs, Rules and Policy Hierarchy…
Azure Architecture Azure Architecture Series

Azure Architecture Series #84 β€” Azure Firewall: SKUs, Rules and Policy Hierarchy

Verified against current vendor documentation on 5 November 2026. Pricing, limits and API behaviour were checked against the official docs on that date. Cloud services change fast — if you are reading this much later, treat the specifics as a starting point and re-check the linked sources.

Business Challenge

Azure Firewall has been the implied answer to three earlier posts without ever being the subject of one. #77 put it in the hub and found its SNAT budget shared by every spoke. #79 pointed the default route at it and found that its SNAT hid the source address the perimeter existed to read. #82 made it the next hop for a routing policy, and #83 established that it is an Azure-native NVA using the same high availability designs as any third-party appliance. In all four it was a box that traffic went through. This post is about what it does with the packet once it arrives.

The starting position is the one safe thing about it:

Deny by default, and every rule is terminating

“By default, Azure Firewall denies all traffic until you manually configure rules to allow traffic. The rules are terminating, so rule processing stops on a match.”

Both halves of that matter, and the second one is where the surprises live. A terminating rule set means the order of evaluation is not a performance detail — it is the policy. Two rule sets containing exactly the same rules enforce different things if they are evaluated in a different sequence, and Azure Firewall's sequence is decided by four separate sorting keys, only one of which is called priority.

The SKU choice is the other half, and it is not the capacity decision it looks like. Basic, Standard and Premium differ by throughput, but they also differ in whether threat intelligence is allowed to block anything, whether you can filter on an FQDN in a network rule at all, and whether the firewall can resolve DNS on behalf of your workloads — which turns out to be load-bearing for the filtering you were buying it for.

Architecture

Diagram: Azure Firewall SKUs, rules and policy hierarchy across five bands. The first band covers the three SKUs. Basic reaches up to 250 Mbps with no fat flow support, threat intelligence in alert mode only which cannot deny traffic, no network level FQDN filtering, no DNS proxy so it uses Azure DNS only, and no web categories. Standard reaches up to 30 Gbps aggregate with 1 Gbps fat flow support, adds threat intelligence in alert and deny mode, network level FQDN filtering, DNS proxy and custom DNS, and FQDN-based web categories. Premium reaches up to 100 Gbps aggregate with 10 Gbps fat flow support on a more powerful virtual machine SKU, and adds outbound TLS termination, fully managed IDPS with over 67,000 rules in more than 50 categories and 20 to 40 plus new rules daily and up to 10,000 customisable rules, full-path URL filtering, and URL-based web categories. Availability zones and built-in high availability are on all three, with no extra load balancers and no extra cost for multi-zone deployment. Inbound TLS termination is listed for Premium as being achieved using Azure Application Gateway rather than natively. The second band is the aggregate versus single flow gap, the fourth time this series has met it: Standard advertises 30 Gbps but a single fat flow caps at 1 Gbps, a factor of thirty, and Premium advertises 100 Gbps but a single flow caps at 10 Gbps, a factor of ten. The third band is the policy hierarchy: a firewall policy contains rule collection groups, which contain rule collections, which contain rules. Three default rule collection groups exist with preset priorities, Default DNAT at 100, Default Network at 200 and Default Application at 300, and these cannot be deleted and their priorities cannot be changed, so reordering means creating custom groups instead. A rule collection group is the first unit processed and follows priority. A rule collection is the second unit processed, carries a single allow or deny action that applies to every rule inside it, and follows priority. A rule is the third unit processed and does not follow priority at all, being evaluated top-down. Priority values run from 100 for the highest priority to 65,000 for the lowest, a span of 64,900, and Microsoft advises spacing collections in increments of 100. The fourth band is the actual evaluation order, which has four keys applied in this nesting: first the rule type, DNAT then Network then Application, which the documentation says wins regardless of rule collection group priority, rule collection priority and policy inheritance; second, within each type pass, parent policy groups before child policy groups; third, rule collection group priority; fourth, rule collection priority; and finally rules top-down within a collection. The firewall iterates through all rule collection groups three times, once per rule type. In Microsoft's own worked example this means a child policy DNAT collection at group priority 650 and collection priority 3000 is evaluated at step 3, ahead of a parent policy network collection at group priority 200 and collection priority 800 at step 4, so the headline rule that the parent always takes precedence is a tie-break inside a type pass rather than an override of type ordering. Threat intelligence filtering runs before all configured rules and can block traffic before any rule is processed. IDPS in alert mode runs in parallel with rule processing; in alert and deny mode it runs inline after the rules engine, and its session drops are silent with no TCP reset sent. The fifth band covers the consequences. Because rules are terminating and network rules always precede application rules, a broad allow network rule on ports 80 and 443 makes an entire deny application rule layer unreachable, which is Microsoft's own Example 1 with google.com. Application rules are never applied to inbound connections at all, so inbound HTTP and HTTPS filtering requires a Web Application Firewall. For HTTP the firewall matches on the Host header and for HTTPS on SNI only, ignoring the packet's destination IP address and using the DNS resolved address from the Host header, and dropping the traffic outright on a port mismatch between the real TCP port and the host header port. A DNAT match exempts traffic from all further network rule processing. The built-in infrastructure rule collection covering the Platform Image Repository, managed disk status storage and Azure diagnostics logging is processed after application rules and before the final deny-all, so a deny-all application collection described as processed last still runs before it. Azure Firewall is stateful, so return traffic on an established TCP or UDP connection is allowed even when an explicit deny rule exists in the reverse direction, while changing a rule to deny previously allowed traffic drops the matching existing sessions outright.
Three SKUs separated by capability, a three-level hierarchy, and four sorting keys of which priority is the third.

The three SKUs

CapabilityBasicStandardPremium
Autoscale ceiling Up to 250 Mbps Up to 30 Gbps Up to 100 Gbps
Fat flow support N/A 1 Gbps 10 Gbps
Threat intelligence filtering Alert only — cannot deny Alert and Deny Alert and Deny
Network-level FQDN filtering (all ports and protocols) Not supported Supported Supported
DNS proxy and custom DNS Not available — Azure DNS only Supported Supported
Web categories Not supported FQDN-based Full-URL based
Outbound TLS termination, IDPS, full-path URL filtering — — Premium only
Deploy without a public IP in Forced Tunnel mode Not supported Supported Supported
Availability zones and built-in HA Yes Yes Yes

The hierarchy, and what each level actually controls

LevelProcessedCarries a priority?What it decides
Rule collection group First unit Yes — 100 to 65,000 Grouping and coarse order. Three defaults exist at 100 (DNAT), 200 (Network) and 300 (Application), and you cannot delete them or change those values.
Rule collection Second unit Yes — 100 to 65,000 The action. Allow or deny is set here, not per rule, and it applies to every rule in the collection.
Rule Third unit No The match condition only. Rules are evaluated “in a top-down approach” in the order they appear.

That middle row is the one worth pausing on. The action lives on the collection, so “allow” and “deny” are properties of a container rather than of a rule. You cannot write a collection that permits two things and blocks a third; you write two collections and give them priorities. Much of the apparent complexity of an Azure Firewall policy is this constraint propagating outwards.

Why This Architecture Holds Up

Because the SKU boundary is capability, not capacity

Read the SKU table as a throughput ladder and Basic looks like Standard for smaller sites. It is not. Three of its limits change what the firewall is able to enforce, regardless of how little traffic you send through it.

The first is the most direct: threat intelligence on Basic is “Alert only” and “cannot deny traffic”. The feature is present, it draws the same Microsoft threat feed, and it will tell you about traffic to a known malicious address after that traffic has completed. A control that observes is a detection capability filed under a prevention heading, and on this SKU that is the only form it comes in.

The second is that Basic has no “Network level FQDN filtering – all ports and protocols” — only application-rule FQDN filtering, which as the rule-processing rules below establish applies to HTTP, HTTPS and MSSQL. So on Basic you cannot filter SSH, RDP or NTP by hostname at all; those are network rules, and network rules on Basic take IP addresses.

The third is the one that compounds the second:

No DNS proxy on Basic, and DNS proxy is what makes FQDN filtering reliable

Basic has “DNS proxy: Not available (uses Azure DNS only)”. And of the proxy itself: “This functionality is crucial for reliable FQDN filtering in network rules.”

So the SKU that cannot do network-rule FQDN filtering is also the SKU missing the mechanism that makes it dependable — and on the SKUs that can, enabling the one without the other is a documented reliability gap rather than a preference.

That last point is the actionable one even for Standard and Premium users. FQDN filtering works by resolving the name and matching the resulting address, so firewall and workload must agree on what the name resolves to. #77 found the symptom of that disagreement — Azure Firewall blocking legitimate traffic on an FQDN DNS mismatch. The DNS proxy is the documented fix, and it is absent from Basic entirely.

One more Basic limitation connects straight back to #79. All three SKUs support forced tunnelling, but “Deployment without public IP address in Forced Tunnel Mode” is a Standard and Premium feature. So a Basic firewall can be forced to send everything to an on-premises next hop and must still carry a public IP address while doing it. The design whose entire purpose is that nothing egresses directly keeps the address that would let it.

Because the headline throughput is an aggregate, and a single flow gets a different number

This series has now met the same pattern four times, and the row that carries it here is called fat flow support:

SKUAdvertised scalabilitySingle fat flowRatio
BasicUp to 250 MbpsN/A—
StandardUp to 30 Gbps1 Gbps30×
PremiumUp to 100 Gbps10 Gbps10×

The number in the product description is what the firewall can process across all flows at once. The number a single large transfer gets is thirty times smaller on Standard and ten times smaller on Premium. A database replication stream, a backup job, a single large file copy — these are one flow, and on Standard one flow is 1 Gbps no matter what the autoscale ceiling says.

The same shape appeared in #73 as aggregate benchmark versus observed per-tunnel throughput, in #76 as gateway aggregate versus per-flow, and in #81 as a Virtual WAN hub's 50 Gbps against 1.5 Gbps for a single TCP flow. Four services, four pairs of figures, and in every case the larger one is the one on the overview page. It is worth treating as a standing question rather than a per-service surprise: when Azure publishes a throughput figure, find the per-flow figure before sizing anything against it.

Because “priority” is the third sorting key, not the first

The hierarchy suggests that a policy is sorted by priority, and the priority range is generous — “any number between 100 (highest priority) to 65,000 (lowest priority)”, a span of 64,900 values, with Microsoft advising “100 increments” so there is room to insert more later.

Then one note removes most of its significance:

Rule type outranks every priority you set

“The system always processes application rules after network rules, and processes network rules after DNAT rules regardless of rule collection group or rule collection priority and policy inheritance.”

And the mechanism behind it is explicit: “The firewall iterates through all rule collection groups three times — once per rule type in order: DNAT, then Network, then Application.” So the real sort is:

KeyWhat it sorts byCan you change it?
1Rule type — DNAT, then Network, then ApplicationNo. Fixed, and it overrides everything below.
2Parent policy before child policy, within a type passNo — inherited policies always win the tie.
3Rule collection group priorityYes.
4Rule collection priorityYes.
5Rule order within a collection, top-downYes, by reordering — there is no priority field.

Which means a number you chose only ever breaks ties inside a group that two fixed rules have already selected. If an application rule is not matching when you think it should, the priority you assigned it is unlikely to be the reason — something in the network pass matched first, and nothing you write at the application level can reach past that.

Because “the parent always takes precedence” is narrower than it sounds

The same page says both of these. First: “rule collection groups in the parent policy always take precedence regardless of the priority of a child policy”, restated as point one of a four-point summary — “The parent policy always takes precedence over the child policy.” Second, in the note quoted above: type ordering wins “regardless of… policy inheritance”.

Those read as contradictory, and Microsoft's own worked example resolves it. In a policy with four groups — BaseRCG1 at 200 and BaseRCG2 at 300 inherited from a parent, ChildRCG1 at 300 and ChildRCG2 at 650 in the child — the published processing order contains this:

StepCollectionTypeGroup (priority)Collection priorityPolicy
3ChDNATRC3DNATChildRCG2 (650)3000Child
4NetworkRC1NetworkBaseRCG1 (200)800Parent

The child policy's collection is evaluated first, despite a worse group priority, a worse collection priority, and being the child. It wins because it is a DNAT rule and the other is a network rule, and the DNAT pass happens before the network pass. So parent precedence is a tie-break inside a type pass, not a general override — which the same example confirms, because BaseRCG2 and ChildRCG1 are both priority 300, and the parent's network collection is evaluated at step 5 while the child's comes at step 6.

This is the detail that matters for anyone running a central policy inherited by business units, which is the normal reason to use policy inheritance at all. A central security baseline cannot guarantee that it is evaluated before a subscription's own rules — it can only guarantee that among rules of the same type. A child policy that wants to pre-empt a parent network rule does not need a better priority; it needs a DNAT rule.

Because one broad network rule makes your whole FQDN layer unreachable

Rules are terminating, and network rules are always evaluated before application rules. Put those two facts together and you get the single most consequential behaviour in Azure Firewall — which Microsoft documents, without alarm, as Example 1:

Microsoft's Example 1

A network rule — action Allow, protocol TCP, source *, destination *, destination ports 80,443.

An application rule — action Deny, target FQDN google.com.

“The connection to google.com is allowed because the packet matches the Allow-web network rule. Rule processing stops here.”

The application rule is not overridden. It is never reached. And a network rule allowing TCP 80 and 443 to anywhere is exactly what gets written early in a deployment to “let web traffic out” while the real policy is still being designed. Once it exists, every FQDN rule, every web category, and on Premium every URL filter and every TLS-inspected match is dead code for ports 80 and 443 — which is to say, for the traffic they were bought to inspect.

The explicit statement is worth keeping to hand: “Application rules evaluate the packet in priority order if there's no network rule match and if the protocol is HTTP, HTTPS, or MSSQL.” Two conditions, both easy to fail silently. The first is defeated by a broad allow. The second means an application rule can never filter anything else — which is why network-level FQDN filtering exists, and why its absence on Basic is a real limit rather than a tier marker.

Because the firewall does not look at the destination IP address it was given

For application rules the matching is done on names, and the mechanism has a sharp edge:

“For HTTP, Azure Firewall looks for an application rule match according to the Host header. For HTTPS, Azure Firewall looks for an application rule match according to SNI only… the firewall ignores the packet's destination IP address and uses the DNS resolved IP address from the Host header. If there's a port mismatch between the actual TCP port and the port in the host header, the firewall drops the traffic.”

Three consequences follow. Matching is only as trustworthy as the name the client supplied, which is why TLS inspection exists and why without it an HTTPS rule is an SNI rule. The firewall's own DNS resolution decides which address a name maps to, which is the mechanism behind #77's mismatch symptom and the reason the DNS proxy is called crucial. And a port mismatch is not a miss that falls through to the next rule — it is a drop, so a host header carrying a port that does not match the connection fails closed rather than being evaluated further.

On the inbound side there is a harder boundary still: “Azure Firewall doesn't apply application rules for inbound connections. So, if you want to filter inbound HTTP/S traffic, use Web Application Firewall.” Inbound is DNAT and network rules only. Every L7 capability in the SKU table — FQDN filtering, web categories, URL filtering — is an egress capability. A Premium firewall in front of a public web application is not inspecting requests to it.

And a DNAT match is the broadest exemption in the product: “if Azure Firewall finds a match, it translates the traffic according to the DNAT rule and allows it. So, the traffic isn't subject to any further processing by other network rules.” Which is why the documentation's advice on DNAT is about scoping the source: “add a specific Internet source to allow DNAT access… and avoid using wildcards.”

Because a deny-all that is “processed last” still is not last

Azure Firewall ships a built-in allow list you did not write: “a built-in rule collection for infrastructure FQDNs that are allowed by default” — the storage Platform Image Repository, managed disks status storage, and Azure Diagnostics and Logging. It sits “after application rules and before the final deny-all rule”, and the override instruction contains a sentence that repays a careful read:

“You can override the built-in infrastructure rule collection by creating a deny all application rule collection that is processed last. It always processes before the infrastructure rule collection.”

So “processed last” means last among your rules. The platform's collection sits below the floor of your policy, and the only way to reach it is to deny everything above it. For anyone writing an explicit deny-all as a policy terminator — good practice, and the way you make an allow list auditable — the thing to know is that it is not the final word unless you intend it to also switch off the platform's own egress.

Because statefulness quietly outranks an explicit deny

Two statements about return traffic sit near each other and point in slightly different directions. One advises an explicit deny for the reverse direction; the other says it is unnecessary — “Creating an allow rule from VNet-A to VNet-B doesn't mean that newly initiated connections from VNet-B to VNet-A are allowed. As a result, you don't need to create an explicit deny rule from VNet-B to VNet-A.” The reconciliation is in what an explicit deny can and cannot do:

An explicit deny does not stop the return packets

“Azure Firewall is stateful, so it allows return traffic for an established TCP or UDP connection… even when an explicit Deny rule exists in the reverse direction. The explicit Deny rule continues to block new connections.”

That is correct firewall behaviour and worth stating plainly, because an explicit reverse deny is often written in the belief that it hardens something. It blocks new connections, which the default deny already did. It does not block the return half of a flow the other direction was permitted to open, and it should not.

One behaviour here is the opposite of what #83 found for the load balancer, and the contrast is instructive. There, established TCP flows survived every backend failing its health probe. Here: “If you change a rule to deny previously allowed traffic, Azure Firewall drops any relevant existing sessions.” A policy change is enforced immediately on connections already in flight. The platform is lenient about an appliance it believes is dead and strict about a rule you have just edited — so a tightening change is a change with an immediate blast radius, not one that takes effect on the next connection.

Because one protocol keyword changed meaning and old rules kept it

A network rule's protocol can be “TCP, UDP, ICMP, or Any IP protocol”, and Any now means genuinely any: “all the IP protocols as defined in the Internet Assigned Numbers Authority Protocol Numbers document.” It did not always:

“Before November 9, 2020, Any meant TCP, or UDP, or ICMP. So, you might have configured a rule before that date with Protocol = Any, and destination ports = '*'. If you don't intend to allow any IP protocol as currently defined, modify the rule to explicitly configure the protocol(s) you want.”

A rule written years ago to mean “TCP or UDP or ICMP” now means every IP protocol in the IANA registry, and nothing about the rule changed to say so. Any Azure Firewall estate predating that date should be audited for Protocol = Any specifically, and it is the sort of thing that no review catches by reading the rule, because the rule still reads exactly as its author intended.

A smaller related detail with the same flavour: “If you explicitly configure a destination port, the rule translates to a TCP+UDP rule.” Specifying a port narrows the protocol for you, which is convenient and also means the protocol field is not always what is enforced.

Because IDPS runs after the decision and drops without saying so

On Premium, IDPS is substantial — “over 67,000 rules in more than 50 categories”, “20 to 40+ new rules released daily”, and “support for customizing up to 10,000 IDPS rules”. Where it sits in the pipeline depends on its mode, and both placements have a logging consequence.

ModePositionWhat you see
Alert In parallel with the rule processing logic An alert on a signature match for inbound and outbound flows. Traffic the rules already allowed or denied “might still generate another log entry”.
Alert and Deny Inline, after the rules processing engine Both engines generate alerts and might block. “Session drops that IDPS performs block the flow silently. So no RST is sent on the TCP level.”

The order is the point: IDPS always inspects after a rule has matched and been logged. So a flow can appear in the logs as allowed by a rule and then be dropped, producing a second Drop entry for the same traffic. A client sees a connection that was permitted and then stopped with no reset — which presents as a timeout, not a refusal, and is therefore diagnosed as a network problem.

Threat intelligence sits at the other end of the pipeline: “those rules have the highest priority. Azure Firewall always processes them first, before network and application rules… can block traffic before Azure Firewall processes any configured rules.” So the full order is threat intelligence, then DNAT, then network, then application, then the infrastructure collection, then deny — with IDPS either beside the whole thing or immediately after it.

Key Architecture Decisions

DecisionChooseBecause
SKU, when the requirement is “block known-bad traffic” Standard at minimum Threat intelligence on Basic is Alert only and cannot deny traffic. Basic gives you the detection, not the control.
SKU, when you need to filter SSH, RDP or NTP by hostname Standard at minimum Network-level FQDN filtering across all ports and protocols is unavailable on Basic, and application rules only cover HTTP, HTTPS and MSSQL.
DNS configuration whenever FQDN rules exist Enable the DNS proxy (Standard or Premium) It is described as crucial for reliable FQDN filtering in network rules. Firewall and workload resolving a name differently is the documented cause of legitimate traffic being blocked.
Sizing against a published throughput figure Size on the fat flow number Standard is 30 Gbps aggregate but 1 Gbps per flow; Premium 100 Gbps but 10 Gbps. A single backup or replication stream gets the small number.
Broad “allow web traffic” network rules Do not write them — put 80 and 443 in application rules Rules are terminating and network rules precede application rules, so an allow on TCP 80/443 to * makes every FQDN, web category and URL rule unreachable. This is Microsoft's Example 1.
Inbound HTTP/S filtering Web Application Firewall, not Azure Firewall Application rules are never applied to inbound connections. Inbound is DNAT plus network rules; all L7 filtering here is egress-only.
DNAT rule sources A specific internet source, never a wildcard A DNAT match exempts the traffic from all further network rule processing, so the DNAT rule is the whole of the policy for that flow.
Reasoning about why a rule did not match Check the type pass before the priority Type ordering overrides group priority, collection priority and inheritance. An unmatched application rule usually means something matched in the network pass.
A central baseline policy inherited by child policies Do not rely on parent precedence alone Parent-first is a tie-break within a type pass. A child DNAT rule is evaluated before any parent network rule, whatever the priorities.
Rule collection priority numbering Space in 100 increments within 100 to 65,000 Microsoft's own advice, and the 64,900-value span is there to be left gappy so collections can be inserted without renumbering.
An explicit deny-all terminator Write it, and know it is not last A deny-all application collection “processed last” still runs before the built-in infrastructure rule collection, which allows platform FQDNs by default.
An explicit deny for the reverse direction Skip it The firewall is stateful, so return traffic on an established connection is allowed regardless. The deny only blocks new connections, which the default deny already did.
Tightening a rule in production Treat it as an immediate change Changing a rule to deny previously allowed traffic drops relevant existing sessions, rather than applying from the next connection.
Auditing an estate older than November 2020 Search for Protocol = Any Any once meant TCP, UDP or ICMP and now means every IANA IP protocol. The rule text did not change, so review cannot catch it by reading.
IDPS mode, when connection behaviour must be explainable Know that Alert and Deny drops silently No RST is sent, and IDPS runs after a rule has already matched and logged, so traffic logs as allowed and then dropped. It presents as a timeout.

Closing Thought

The hierarchy diagram makes Azure Firewall look like a sorted list, and almost everything surprising about it comes from the fact that it is three sorted lists walked in sequence. DNAT, then network, then application, with your priorities operating only inside each pass. Once that is the mental model, the behaviours stop being quirks: an application rule that never fires, a central policy a child can pre-empt, a web category feature that does nothing because of a rule written before anyone thought about categories. All three are the same fact seen from different directions.

If there is one thing to take from this and check today, it is Example 1. A network rule allowing TCP 80 and 443 to everywhere is the most natural thing to write while a policy is still being built, it looks like a sensible default, and it silently disables every L7 control above it. The Premium SKU exists almost entirely to inspect that traffic — TLS inspection, URL filtering, full-URL web categories, IDPS signatures — and one network rule in the wrong layer makes all of it unreachable for the ports that matter. Nothing errors, nothing logs a conflict, and the firewall reports itself as working.

The SKU half has a similar shape. Read as a throughput ladder, Basic is a smaller Standard. Read as a capability list, it is a firewall whose threat intelligence cannot block, which cannot filter a hostname outside three protocols, and which lacks the DNS proxy that the filtering it does have depends on for reliability. Those are not limits you grow out of at 250 Mbps. They are limits on what the control can be asked to enforce, and the question they settle is not how much traffic you have but what you were planning to claim about it.

Next in this series

#85 moves up a level to the management plane: Azure Firewall Manager and secured virtual hubs — how one policy reaches many firewalls, and what changes when the firewall lives in a Virtual WAN hub rather than a virtual network.

Official Azure Reference

Comments

How was your experience?
Your feedback helps improve this site.
PoorExcellent