Both large clouds sell a managed web application firewall, both point a rule set at roughly the same list of vulnerabilities, and they disagree about the most consequential thing a firewall does. AWS WAF stops at the first rule whose action terminates the evaluation. Azure WAF's managed sets add up a severity-weighted score and act at a threshold you cannot move. Everything else follows.
12 March 2026·8 min read·securitycloud
A firewall in front of a web application answers one question per request, and the two clouds have built genuinely different machines for answering it. Both show you a graph of blocked requests within an hour of being switched on, which is why the difference survives procurement and surfaces in the first incident. AWS WAF asks whether a rule matched. Azure WAF, on its managed sets, asks how suspicious the request looks in total.
In an AWS web ACL every rule carries a unique numeric priority, and evaluation runs from the lowest number upward until a match terminates it or the rules run out. Allow and Block terminate. Count does not, and CAPTCHA and Challenge terminate only when the request arrives without a valid token. If nothing terminates, the web ACL's default action decides. So a refused request is refused by exactly one rule, and the log names it.
Azure WAF's managed sets do not stop at a match. Every rule carries a severity, and the severity adds to a running total: Critical contributes 5, Error 4, Warning 3, Notice 2. The WAF acts at 5 or more. One Critical match is therefore enough on its own, and so is a pair of Warnings, neither of which Microsoft considers sufficient evidence by itself.
That is the difference, and everything downstream is a consequence of it. One product hands you a decision attributable to a rule. The other hands you a decision attributable only to a sum. Which is more accurate depends on the attack. Which is easier to live with depends on whether anybody in your organization can explain a refusal to the customer who is on the phone about it.
On AWS you find the rule and take it out of the path. The log names the terminating rule, so the work is deciding what to do about one named thing. Override its action to Count inside the managed group, add a scope-down statement so the group never sees the request, or run the group in Count mode and write your own rule matching the label it stamped. Different mechanisms, all aimed at a single identified rule.
On Azure you find the rules, plural, and do arithmetic. A block logs a matched entry per contributing rule plus a separate entry for the score being exceeded, so the fix is working out which contributions to remove until the total falls below 5. An exclusion names a header, cookie, query argument or body field, and suppresses that field's value - so it cannot help when the field's name is what tripped the rule, and it applies policy-wide rather than to one route.
The threshold is not a dial, which surprised me. I assumed the escape hatch was raising the number, and it is not there: Microsoft documents the threshold as 5 and exposes nothing that moves it. On Front Door you choose what happens when it is crossed, Block or Log or Redirect. What you actually tune is which rules run and at which paranoia level, with levels 3 and 4 unsupported. The blunt instrument is switching whole rules off.
And on Azure a custom rule is not an exclusion. Custom rules you write are evaluated ahead of the managed set and behave the AWS way, first match wins and nothing after it runs. Which means a permissive custom rule added to let one awkward request through does not exempt it from the rule that was blocking it. It exempts it from the entire managed set. The two models live in one policy and that is the seam between them.
Scoring exists because single-rule matching has a real hole. A request can be built to trip three separate Warning-severity checks and nothing Critical, and under first-match-wins it passes, because no individual rule was confident enough to act on its own evidence. Under scoring it reaches 9 and is refused. That is not a theoretical advantage; it is the specific thing the accumulating model was built for, and it works.
The same property is the cost. A request can reach 5 without any rule being wrong: a support ticket containing markup, a password with quote characters, an upload whose bytes read like four mild things at once. Nothing there was an attack, no single rule claimed it was, and it was still refused. Explaining that means explaining a scoring model, which is a conversation nobody wants to have twice.
So I am not going to resolve this, because it does not resolve. The models fail differently and want different people tuning them: one wants somebody who reads a log and reasons about a rule, the other somebody comfortable with no rule being individually responsible. Nobody tells you at purchase which of the two you are hiring, and that omission does more damage than either design.
AWS puts one web ACL in front of several kinds of resource. A CloudFront distribution, an Application Load Balancer, an API Gateway REST API, an AppSync GraphQL API, a Cognito user pool, an App Runner service, a Verified Access instance or an Amplify app. What the firewall can read varies with that choice: body inspection is fixed at 8 KB behind a load balancer and defaults to 16 KB elsewhere, raisable to 64 KB for a surcharge. The same rule is a different control depending on where it sits.
Azure puts a policy on a delivery network or on a gateway. This is the relationship people get wrong, and I had it wrong myself until recently. Front Door is not a firewall, it is a content delivery network, and Azure WAF is a policy attached to it for global coverage or to an Application Gateway for regional coverage. Those are separate Azure resource types with separate schemas, and the portal makes you commit on the first field of the create blade.
Global against regional is a real choice, not a preference. A global policy is one configuration governing every point of presence, which is what you want for consistency and is exactly what makes a bad rule a global event; I have written about what a single global control plane does to a recovery plan. A regional attachment gives you a smaller blast radius and the standing cost of keeping several configurations honest.
Azure has an actual mode. A policy is created in Detection and moving to Prevention is one setting. Microsoft's guidance is to stay there while you work the logs, it warns the process might take several weeks, and it is unusually blunt about the trade: detection mode is useful while you tune, and it provides no protection. AWS has no web ACL wide equivalent. Count is the only mechanism, applied per rule, which for a managed group means overriding its rules one at a time.
I want to correct something I believed going in. I assumed both managed sets descended from the same open project, and that is only half right. Azure's is explicitly baselined off the OWASP Core Rule Set, with Microsoft threat intelligence rules layered on and some OWASP originals disabled in favor of replacements. AWS names its group the core rule set as well, then describes it only as covering some of the vulnerabilities described in OWASP publications. The lineage claim is never made.
Either way the first week is not attacks. It is an editor pasting markup into a form, a password manager generating quote characters, an authentication header a rule has decided is path traversal. This is the work, and a team that has not budgeted for it does not end up with a badly tuned firewall. It ends up with one that never leaves detection.
AWS says in writing that its rate limiting is approximate. The documentation is direct: it is not intended for precise request-rate limiting. AWS estimates the rate with an algorithm weighting recent requests more heavily, and warns traffic can run over your limit for several minutes before the rule engages. So the number you configure has to sit well under the number your application actually breaks at.
Azure describes the mechanism rather than using the word. Front Door explains that counters live on individual Front Door servers, that a client opening a new connection per request can reach one whose counter has not caught up, and that at low thresholds requests over the limit will get through - Microsoft puts the practical floor near 200 requests per minute. Application Gateway is blunter, saying thresholds are not always enforced exactly as defined.
The keys you can count by differ, and that constrains design. An AWS rate-based rule aggregates on up to five custom keys: a header, a cookie, a query argument, a URI path, a TLS fingerprint, an autonomous system number. Front Door counts by socket address, by geography, or not at all. That is the gap between rate limiting per tenant and rate limiting per source address, and behind a corporate proxy the second is one address standing in for a great many people.
Bot handling sits on its own meter. AWS Bot Control is a subscription per web ACL plus a per-request charge, with the targeted level - browser interrogation, fingerprinting, silent challenges - priced an order of magnitude above the common level. Azure ships its bot rules as a separate managed set. Either way the move that matters is scoping the expensive rules to the endpoints needing them rather than to everything.
AWS itemizes. A web ACL is $5 per month, each rule and rule group $1 per month, requests $0.60 per million. Then capacity, which catches people: the base price includes 1,500 web ACL capacity units, the ceiling is 5,000, and every 500 above the allowance adds $0.20 per million requests. The core rule set alone declares 700. Capacity is not only a limit on configuration, it is a price curve on every request you serve.
Azure bundles. Managed rule sets are a property of the Premium Front Door tier rather than a line item, so Standard gets custom rules and rate limiting but not the OWASP-derived set, and an Application Gateway with WAF bills as gateway hours plus capacity units. The firewall never appears as its own number, which makes it look free and makes what the control costs genuinely hard to answer.
On both, logging is the line item nobody forecasts. Full request logging produces a volume unrelated to how much you blocked, because you log what you allowed as well, and it lands in a different service with its own pricing. AWS includes an allowance of vended log delivery scaled to request count, which helps and does not solve it. Budget the logs before you budget the firewall.
A firewall is a dependency with its own change control. A rule set update changes how every request to your application is judged, written by somebody else on their schedule. AWS lets you pin a static version while reserving the right to patch static versions when a threat warrants. Azure warns that changing rule set version through the portal resets rule state, actions and rule-level exclusions to the new defaults, which can quietly discard a year of tuning.
Detection mode forever is the common outcome, not the rare one. The failure I have seen most is not a badly tuned firewall refusing customers. It is one switched on in detection, producing findings nobody had time to work through, and left there. It costs money, satisfies a questionnaire and blocks nothing. If you cannot name the person reading those logs weekly for the next quarter, you are buying a compliance artifact and should price it as one.
The evidence you get is the evidence the vendor chose to give you. When a customer insists their request was legitimate you will open a log and explain. Azure publishes its managed sets in full, so you can point at the rule, its severity and its contribution. AWS withholds rule detail deliberately, to protect the providers' intellectual property and to stop attackers designing around published rules. Both positions are defensible, and they are different conversations.
I should narrow this, because I have made a mechanism sound like a purchasing criterion and for most organizations it is not one. If you are never going to tune, and most teams genuinely are not, the scoring model is probably kinder, since it refuses ordinary traffic on one nervous rule less often. And nobody picks a cloud for its firewall. The application is already somewhere, the firewall attaches to what is there, and this comparison collapses into a paragraph in a design document.
What stays with me travels further than either product. Every detection system you will ever run makes the same choice: a verdict you can trace to one rule, or a verdict that emerged from several things being slightly wrong at once. The first is easier to explain and easier to evade. The second catches what the first misses and cannot say which part of it was the reason. Buying one without knowing which you bought is how a control spends two years in detection mode, generating evidence nobody reads.