Azure Network Security Groups vs Azure Firewall vs Application Gateway: Decision Guide
A team routes all traffic through Azure Firewall Premium at $1.84/hour, then discovers half their rules could have been NSG entries at zero marginal cost. Another team relies entirely on NSGs, then gets hit by a SQL injection that a WAF would have caught. This guide maps each service to the traffic layer it actually protects, provides side-by-side capability matrices, and gives you the decision framework for when to use each one alone or in combination.
The $43,000 Mistake: Choosing the Wrong Network Security Layer
A financial services team migrated 40 workloads to Azure and routed every packet through Azure Firewall Premium. Monthly bill: $1,350 for the firewall alone, before data processing charges. When they audited their rule set six months later, 62% of the rules were simple port/protocol allow-deny entries between subnets: the exact job that Network Security Groups handle for free. The remaining 38% were FQDN-based outbound rules and TLS inspection policies that genuinely needed Azure Firewall. They refactored, cut their network security spend by $520/month, and actually improved their security posture because the NSG rules were enforced at the NIC level, closer to the workload.
On the opposite end, a SaaS company protected their public-facing APIs with NSGs only. Port 443 inbound, allow. Port 80 inbound, redirect. They had no layer 7 inspection anywhere in the path. A basic SQL injection through a query parameter took down their customer database. An Application Gateway with WAF in Prevention mode would have caught the payload before it reached the backend.
These are not edge cases. They are the two most common Azure network security architecture mistakes: over-relying on a single tool, or choosing the expensive option when the cheap one is sufficient. The decision is not "which one is best." It is "which one protects which layer, and where do they overlap."
What Each Service Actually Does
Network Security Groups: Layer 3/4 Packet Filtering
NSGs are stateful packet filters attached to subnets or individual NICs. They evaluate five-tuple rules: source IP, source port, destination IP, destination port, and protocol. They make allow-or-deny decisions based on these fields and nothing else. They cannot read HTTP headers, inspect TLS payloads, resolve FQDNs, or understand application-layer protocols.
What NSGs do well:
- Micro-segmentation between subnets (e.g., web tier cannot talk to database tier on port 22)
- Restricting management access (allow RDP/SSH only from a jump box subnet)
- Service tag-based rules (
AzureLoadBalancer,VirtualNetwork,Internet) - Application Security Group (ASG) based rules for role-based segmentation
What NSGs cannot do:
- Block traffic to a specific FQDN (e.g., block
evil.example.comwhile allowinggood.example.comon the same IP) - Inspect encrypted traffic
- Detect or prevent application-layer attacks (SQLi, XSS, command injection)
- Log packet payloads or HTTP request content
- Perform stateful IDPS (intrusion detection/prevention)
Azure Firewall: Layer 3-7 Network Security Appliance
Azure Firewall is a managed, stateful firewall service with two SKUs: Standard and Premium. Standard provides FQDN filtering, network rules, threat intelligence-based filtering, and centralized logging. Premium adds TLS inspection, IDPS (signature-based intrusion detection), URL filtering, and web categories.
Azure Firewall sits in a dedicated AzureFirewallSubnet and acts as a next-hop for routed traffic via UDRs (User Defined Routes). It processes traffic at the network edge or between spoke VNets in a hub-and-spoke topology.
What Azure Firewall does well:
- FQDN-based outbound filtering (allow
*.ubuntu.comfor patching, deny everything else) - Centralized east-west traffic inspection between VNets
- Threat intelligence feed integration (block known-bad IPs/FQDNs)
- TLS inspection for outbound HTTPS traffic (Premium only)
- IDPS with 67,000+ signatures updated daily (Premium only)
- DNS proxy for FQDN resolution in network rules
What Azure Firewall does not replace:
- WAF functionality for inbound web traffic (no OWASP CRS rule engine)
- DDoS protection (separate Azure DDoS Protection service)
- Application-level authentication or authorization
For a deeper comparison of Standard vs Premium capabilities and when the upgrade is justified, see the Azure Firewall Premium vs Standard guide.
Application Gateway with WAF: Layer 7 Ingress Protection
Application Gateway is a layer 7 load balancer with an optional Web Application Firewall (WAF) component. The WAF runs OWASP Core Rule Set (CRS) 3.2 or the newer DRS (Default Rule Set) 2.1, providing protection against the OWASP Top 10 web application vulnerabilities. It operates in Detection or Prevention mode.
Application Gateway sits in front of your web backends (App Service, AKS, VMs) and terminates TLS. It can route based on URL path, hostname, HTTP headers, and query strings. The WAF inspects the full HTTP request and response.
What Application Gateway + WAF does well:
- SQL injection, XSS, and command injection detection/prevention
- Bot protection with managed bot rule sets
- Rate limiting per client IP
- Custom WAF rules for application-specific patterns
- TLS termination and certificate management
- Cookie-based session affinity
- URL path-based routing to multiple backends
What Application Gateway does not do:
- Filter outbound traffic from your workloads
- Inspect non-HTTP protocols (RDP, SSH, SQL, custom TCP)
- Provide network-level micro-segmentation
- Act as a centralized firewall for east-west VNet traffic
Side-by-Side Capability Matrix
| Capability | NSG | Azure Firewall Standard | Azure Firewall Premium | App Gateway WAF |
|---|---|---|---|---|
| OSI layer | 3-4 | 3-7 | 3-7 | 7 |
| IP/port filtering | Yes | Yes | Yes | Limited (via WAF rules) |
| FQDN filtering | No | Yes | Yes | No (hostname routing only) |
| TLS inspection | No | No | Yes | Terminates TLS |
| IDPS (signature-based) | No | No | Yes (67K+ sigs) | No |
| OWASP CRS/DRS WAF | No | No | No | Yes |
| Bot protection | No | No | No | Yes |
| Threat intel feed | No | Yes | Yes | No |
| HTTP header inspection | No | No | Limited | Full |
| URL filtering | No | No | Yes | Yes (path routing) |
| East-west filtering | Yes (subnet) | Yes (hub routing) | Yes (hub routing) | No |
| Outbound filtering | Yes (basic) | Yes (FQDN/rules) | Yes (FQDN/TLS) | No |
| Marginal cost per rule | $0 | Included in base | Included in base | Included in base |
| Base cost (approx/month) | Free | ~$912 | ~$1,325 | ~$175 (v2 Standard) |
| Data processing cost | Free | $0.016/GB | $0.016/GB | $0.008/GB (first 10TB) |
The Decision Framework
Question 1: What Traffic Direction Are You Protecting?
This is the most important question because it immediately eliminates options:
Inbound web traffic (HTTP/HTTPS from the internet to your app): Application Gateway with WAF. Azure Firewall can sit in front of Application Gateway for IP-based pre-filtering, but the WAF layer is what catches application-layer attacks. NSGs on the Application Gateway subnet should restrict source IPs to known ranges or Internet plus GatewayManager tags as required.
Outbound traffic (workloads reaching the internet or external APIs): Azure Firewall. NSGs can block outbound by IP, but cannot filter by FQDN. If your workload needs to reach api.github.com but nothing else, only Azure Firewall provides that control. For a zero trust architecture, outbound filtering is not optional.
East-west traffic (VNet-to-VNet or subnet-to-subnet): Start with NSGs. If you need FQDN filtering or IDPS between internal segments, add Azure Firewall in a hub VNet with spoke-to-spoke routing. Most organizations do not need layer 7 inspection on internal traffic until they hit specific compliance requirements (PCI-DSS, for example).
Management plane traffic (RDP, SSH, bastion access): NSGs plus Azure Bastion. No firewall needed for this specific flow.
Question 2: What Does Compliance Require?
| Compliance Framework | Typical Network Control Requirement | Minimum Service |
|---|---|---|
| PCI-DSS v4.0 | WAF on all public-facing web apps, segmentation between CDE and non-CDE | App Gateway WAF + NSGs |
| NIST 800-53 (FedRAMP High) | Boundary protection, IDPS, encrypted traffic inspection | Azure Firewall Premium + App Gateway WAF |
| SOC 2 Type II | Network segmentation, access logging | NSGs + Flow Logs (minimum) |
| ISO 27001 | Network security controls, monitoring | NSGs + Azure Firewall Standard |
| HIPAA | Access controls, audit logging, encryption in transit | NSGs + Azure Firewall Standard + App Gateway WAF |
Question 3: What Is the Cost Constraint?
Here is the honest cost breakdown for a typical three-tier application processing 500 GB of traffic per month:
NSG only:
Base cost: $0
Data processing: $0
Flow logs (LA): ~$115/month (500GB ingestion at standard tier)
Total: ~$115/monthAzure Firewall Standard:
Base cost: ~$912/month
Data processing: $8/month (500GB x $0.016)
Total: ~$920/month
Azure Firewall Premium:
Base cost: ~$1,325/month
Data processing: $8/month
Total: ~$1,333/month
Application Gateway v2 (WAF_v2 tier):
Base cost: ~$246/month (fixed + capacity units)
Data processing: ~$4/month (500GB x $0.008)
Total: ~$250/month
Full stack (NSG + Firewall Standard + App GW WAF):
Total: ~$1,285/month
The pattern that catches most teams: Azure Firewall's base cost runs 24/7 whether you process 1 GB or 1 TB. If you only need outbound FQDN filtering for a few workloads, consider whether Azure Firewall Basic (preview, ~$273/month) or even just NSGs with service endpoints will satisfy the requirement.
Architecture Pattern 1: NSG-Only (Small Workloads, Internal Apps)
Use when: internal line-of-business apps with no public-facing endpoints, no compliance mandate for IDPS or WAF, cost-sensitive environments.
resource webSubnetNsg 'Microsoft.Network/networkSecurityGroups@2024-01-01' = {
name: 'nsg-web-subnet'
location: location
properties: {
securityRules: [
{
name: 'AllowHTTPSFromCorpnet'
properties: {
priority: 100
direction: 'Inbound'
access: 'Allow'
protocol: 'Tcp'
sourceAddressPrefix: '10.0.0.0/8'
destinationAddressPrefix: '*'
destinationPortRange: '443'
sourcePortRange: '*'
}
}
{
name: 'AllowAppToDb'
properties: {
priority: 200
direction: 'Outbound'
access: 'Allow'
protocol: 'Tcp'
sourceAddressPrefix: 'VirtualNetwork'
destinationAddressPrefix: '10.1.2.0/24'
destinationPortRange: '1433'
sourcePortRange: '*'
}
}
{
name: 'DenyAllOutboundInternet'
properties: {
priority: 4000
direction: 'Outbound'
access: 'Deny'
protocol: '*'
sourceAddressPrefix: '*'
destinationAddressPrefix: 'Internet'
destinationPortRange: '*'
sourcePortRange: '*'
}
}
]
}
}Pair this with NSG Flow Logs v2 sent to a Log Analytics workspace for traffic visibility:
az network watcher flow-log create \
--name flowlog-web-subnet \
--nsg nsg-web-subnet \
--resource-group rg-networking \
--storage-account stflowlogs \
--workspace myLogAnalyticsWorkspace \
--traffic-analytics true \
--interval 10 \
--log-version 2
Limitations of NSG-Only
- No FQDN-based outbound control: if a VM needs to reach
packages.microsoft.combut not arbitrary internet destinations, NSGs cannot express that rule - No logging of denied traffic payloads: you see that a packet was dropped, not what it contained
- No centralized rule management across VNets: each NSG is independently managed
- No TLS inspection capability
Architecture Pattern 2: Hub Firewall + Spoke NSGs (Enterprise Standard)
Use when: multiple VNets in hub-and-spoke topology, compliance requirements for outbound filtering and IDPS, centralized security operations.
This is the architecture pattern that Defender for Cloud recommends for enterprise Azure environments. Azure Firewall sits in the hub VNet. Spoke VNets route all outbound and cross-spoke traffic through the firewall via UDRs. NSGs on spoke subnets handle micro-segmentation within each spoke.
resource spokeRouteTable 'Microsoft.Network/routeTables@2024-01-01' = {
name: 'rt-spoke-to-firewall'
location: location
properties: {
disableBgpRoutePropagation: true
routes: [
{
name: 'default-to-firewall'
properties: {
addressPrefix: '0.0.0.0/0'
nextHopType: 'VirtualAppliance'
nextHopIpAddress: firewallPrivateIp
}
}
{
name: 'spoke-to-spoke-via-firewall'
properties: {
addressPrefix: '10.0.0.0/8'
nextHopType: 'VirtualAppliance'
nextHopIpAddress: firewallPrivateIp
}
}
]
}
}The key design decision: what rules go on the firewall vs. the NSGs? Put on NSGs:
- Port/protocol restrictions between subnets within the same spoke
- Application Security Group memberships for role-based access
- Deny rules for management ports (SSH, RDP) except from bastion subnet
- Service tag rules (
AzureActiveDirectory,AzureMonitor)
- FQDN-based outbound rules (allow
*.windowsupdate.com, deny all) - Threat intelligence filtering
- Cross-spoke traffic inspection
- TLS inspection for outbound HTTPS (Premium)
- IDPS signatures (Premium)
- DNS proxy for conditional forwarding
This separation matters operationally. NSG changes are scoped to the spoke team's resource group and can be delegated. Firewall rules are centrally managed by the network security team. Mixing the two creates confusion about who owns which control.
Architecture Pattern 3: Full Stack (Regulated, Public-Facing)
Use when: public-facing web applications in regulated industries, PCI-DSS or FedRAMP environments, workloads processing sensitive data with internet exposure.
The traffic flow:
Internet → DDoS Protection → Application Gateway + WAF → Backend Subnet (NSG) → Azure Firewall (outbound)Application Gateway handles inbound layer 7 protection. Azure Firewall handles outbound filtering and east-west inspection. NSGs handle subnet-level micro-segmentation. Each layer covers a different attack surface.
# Create Application Gateway with WAF v2
az network application-gateway waf-policy create \
--name waf-policy-prod \
--resource-group rg-networking \
--type OWASP \
--version 3.2# Enable bot protection
az network application-gateway waf-policy managed-rule rule-set add \
--policy-name waf-policy-prod \
--resource-group rg-networking \
--type Microsoft_BotManagerRuleSet \
--version 1.0
# Set to Prevention mode
az network application-gateway waf-policy policy-setting update \
--policy-name waf-policy-prod \
--resource-group rg-networking \
--state Enabled \
--mode Prevention \
--max-request-body-size-kb 128 \
--request-body-check true
KQL: WAF Block Events
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.NETWORK"
| where Category == "ApplicationGatewayFirewallLog"
| where action_s == "Blocked"
| summarize BlockCount = count() by ruleId_s, Message = message_s, bin(TimeGenerated, 1h)
| order by BlockCount desc
| take 20
KQL: Azure Firewall Denied Connections
AZFWNetworkRule
| where Action == "Deny"
| summarize DeniedCount = count() by
SourceIp = SourceIp,
DestinationFqdn = coalesce(Fqdn, DestinationIp),
DestinationPort = DestinationPort,
Protocol
| order by DeniedCount desc
| take 20
Common Mistakes and How to Avoid Them
Mistake 1: Using Azure Firewall as a WAF
Azure Firewall Premium has IDPS and URL filtering, which sounds like WAF functionality. It is not. IDPS detects network-layer attack signatures (port scans, exploit payloads in non-encrypted traffic, known C2 protocols). The OWASP CRS rule engine in Application Gateway WAF detects HTTP-layer attack patterns (SQL injection in query parameters, XSS in POST bodies, path traversal in URLs). These are fundamentally different detection engines for different attack surfaces.
If your application receives HTTP traffic from the internet and you only have Azure Firewall in front of it, you are not protected against OWASP Top 10 attacks.
Mistake 2: NSGs on the AzureFirewallSubnet
Do not attach NSGs to the AzureFirewallSubnet. Azure Firewall manages its own traffic filtering, and NSGs on its subnet create conflicts that result in asymmetric routing, dropped health probes, and firewall availability issues. Microsoft explicitly states this in the documentation: the AzureFirewallSubnet must not have an NSG.
The same applies to GatewaySubnet for VPN/ExpressRoute gateways. These are system-managed subnets.
Mistake 3: Allowing Port 443 in NSG and Calling It Secure
An NSG rule that allows TCP 443 inbound from Internet tells you exactly one thing: the protocol is TCP and the port is 443. It tells you nothing about what is inside the TLS tunnel. A SQL injection payload, a web shell upload, a credential stuffing attack: all of these arrive on port 443 and pass the NSG without inspection.
Port 443 allowed in an NSG is a network-level decision, not a security control. The security control is what inspects the traffic after TLS termination.
Mistake 4: Deploying Azure Firewall Without UDRs
Azure Firewall has no effect on traffic unless the traffic is routed to it. Deploying Azure Firewall and adding rules without creating UDRs on the spoke subnets is a common configuration error that creates a false sense of security. The firewall exists but never sees the traffic.
Verify with this check:
# List effective routes for a NIC to verify traffic goes through the firewall
az network nic show-effective-route-table \
--name vm-web-nic \
--resource-group rg-spoke-web \
--output tableThe output should show 0.0.0.0/0 with next hop type VirtualAppliance pointing to the firewall's private IP. If it shows Internet as the next hop, traffic is bypassing the firewall.
Mistake 5: Ignoring Azure Firewall Basic
Azure Firewall Basic (generally available since 2024) supports network rules, application rules with FQDN filtering, and threat intelligence at a fixed rate of approximately $273/month. It does not support IDPS, TLS inspection, or web categories. For workloads that need centralized FQDN-based outbound filtering without the full Premium feature set, Basic can reduce costs by 75% compared to Premium.
The tradeoff: Basic has a fixed throughput of 250 Mbps. For dev/test environments or small production workloads, that is sufficient. For high-throughput production environments, Standard or Premium is required.
When to Combine vs. When to Choose One
| Scenario | Recommended Stack | Why |
|---|---|---|
| Internal LOB app, no internet exposure | NSGs only | No inbound attack surface, no outbound FQDN requirement |
| Internal app needing outbound FQDN control | NSGs + Azure Firewall Basic | Cost-effective outbound filtering |
| Public web app, startup budget | NSGs + App Gateway WAF | WAF covers the inbound attack surface |
| Multi-VNet enterprise, no public apps | NSGs + Azure Firewall Standard | Centralized east-west and outbound control |
| Public web app in regulated industry | NSGs + Azure Firewall Standard + App Gateway WAF | Full inbound/outbound coverage |
| Sensitive workloads needing TLS inspection | NSGs + Azure Firewall Premium + App Gateway WAF | Maximum inspection depth |
Integration with Defender for Cloud
Defender for Cloud's CSPM capabilities provide recommendations for all three services:
- NSGs: Detects subnets without NSGs, overly permissive rules (allow all inbound), and missing flow logs
- Azure Firewall: Flags firewall instances without diagnostic logging, threat intel in alert-only mode (should be deny)
- Application Gateway: Detects WAF in Detection mode (should be Prevention for production), missing WAF policies, and outdated CRS versions
Enable the Defender for Cloud network security recommendations and review them weekly. The most commonly flagged item across enterprise Azure tenants is NSG rules that allow 0.0.0.0/0 inbound on management ports, typically left over from initial deployment testing.
Hardening Checklist
- [ ] NSGs attached to every subnet except
AzureFirewallSubnet,GatewaySubnet, andAzureBastionSubnet - [ ] NSG Flow Logs v2 enabled with Traffic Analytics on all production NSGs
- [ ] No
Allow *inbound rules fromInterneton any NSG except for Application Gateway health probes - [ ] Application Security Groups used for role-based micro-segmentation instead of raw IP ranges
- [ ] Application Gateway WAF in Prevention mode for all public-facing web applications with CRS 3.2 or DRS 2.1
- [ ] WAF custom rules configured for application-specific patterns (API key formats, rate limits)
- [ ] Azure Firewall UDRs verified on all spoke subnets routing
0.0.0.0/0to the firewall private IP - [ ] FQDN-based outbound rules defined on Azure Firewall for all workloads with internet access requirements
- [ ] Threat intelligence set to Alert and Deny on Azure Firewall (not Alert only)
- [ ] TLS inspection enabled on Azure Firewall Premium for outbound HTTPS traffic to untrusted destinations
- [ ] Diagnostic logs enabled on all three services sent to a central Log Analytics workspace
- [ ] KQL alerts deployed for WAF blocks exceeding baseline and firewall deny spikes
- [ ] Defender for Cloud network recommendations reviewed and resolved on a weekly cadence
- [ ] Azure Firewall Basic evaluated for dev/test environments to reduce cost without losing FQDN filtering
Recommended tool: Pluralsight
Level up your security skills with expert-led courses. Free 10-day trial, then access thousands of courses across cloud security, networking, and certifications.
Get weekly security insights
Cloud security, zero trust, and identity guides — straight to your inbox.
Continue Learning
Cloud Security Engineer Roadmap
Protect cloud workloads at scale.
Microsoft Cloud Solution Architect
Cloud Solution Architect with deep expertise in Microsoft Azure and a strong background in systems and IT infrastructure. Passionate about cloud technologies, security best practices, and helping organizations modernize their infrastructure.
Share this article
Questions & Answers
Related Articles
Need Help with Your Security?
Our team of security experts can help you implement the strategies discussed in this article.
Contact Us