Skip to content

Why a WAF never leaves monitoring mode

Many WAFs never move to blocking. The reason is not technical: the numbers needed to make the move were never agreed in advance.

WAF / ADR
/
2026-04-27
/
5 min read

Monitoring was supposed to be temporary

A WAF is normally switched on in observation mode: rules run, events are recorded, nothing is blocked. That is the right beginning — nobody drops a rule set onto a live site on day one.

The problem is that the exit condition for that stage is never written down. "Let us watch it for a couple of weeks" is said, and the two weeks stretch.

A year later the system is still counting events. Nobody is willing to switch it to blocking, because nobody knows precisely what would be blocked.

Why the fear is justified

The fear has a basis: a generic rule set produces false positives on any real application. An HTML editor in a CMS looks like SQL injection; special characters in a search box match an attack pattern.

The second reason is asymmetric accountability. A blocked real user is visible immediately and someone is blamed. A missed attack surfaces months later, and by then nobody connects it to a WAF setting.

So the decision to move has to rest on a number agreed beforehand, not on personal nerve.

Figure 1Monitoring is the name of a stage, not of a steady state. Selective blocking begins once the baseline exists — and that is the step most deployments never take.

The correct order of stages

The right path has four stages. First, observation: rules run, nothing is blocked. Second, baselining: how often each rule fires and what share of those firings is real traffic.

Third, selective blocking: the most precise rules move to blocking while the rest stay in observation. Fourth, full enforcement.

One detail matters: stages are crossed per route, not per site. `/api/login` and `/admin` can block on day one; the content editor is reached last.

What a baseline consists of

A baseline is not the sentence "we average 4,000 events a day". It is computed per rule: how many times it fired, on which routes, for which users, at which hours.

Then one question is asked of each rule: what share of these firings is a real attack? If the answer is near 100%, the rule is ready to block. If it is 50%, the rule needs narrowing first.

This work is manual and cannot be rushed. But it is done once, and after it the decision to move becomes a technical question.

A false-positive budget

The condition for moving has to be written as a number. A practical form: below 0.1% false positives on a route, blocking is enabled; above 1%, the rule goes back for rework.

For values in between there is an intermediate response: require an additional check rather than blocking. The user is not lost, and an automated tool stops.

Without a budget every complaint becomes its own argument, and arguments always resolve towards loosening. With a number the question changes: does this rule fit the budget?

Figure 2A rule is judged on two axes: does it catch the attack, and does it leave real traffic alone. Only the upper-right cell moves to blocking.

How an exception is written

When a false positive is found, the easiest fix is to switch the rule off. It is also the worst, because the rule then stops applying across the whole site.

A correct exception is narrow: a specific route, a specific field, a specific rule id. "Rule 942100 does not apply in the editor’s body field" is an exception. "942100 is off" is a hole.

And every exception needs an expiry and an owner. An exception with no expiry is never revisited; one with no owner leaves nobody who remembers why it exists.

What a blocked request looks like

The block page is part of the product too. It needs three things: a short statement of what happened, an event identifier, and a way to make contact.

The identifier matters most. Without it the user writes "the site is broken" and support goes hunting through logs. With it, the lookup takes a minute.

And the block page must not tell an attacker which rule fired. The identifier is internal; the explanation is generic.

Figure 3The move condition is written as a number. In-between values get an in-between response: require a check rather than blocking.

A checklist for the move

Four questions need answers before blocking is switched on. Has the baseline been collected, and is the false-positive share known per rule? Is the budget written as a number? Do exceptions carry an expiry and an owner? Does the block page show an event identifier?

A fifth question is about process: who can roll blocking back, and how quickly? If the answer is "only the provider, during business hours", you should not move yet — and that is the correct decision.

Once the list is closed, the move is a technical operation. Until it is, any decision to move remains a personal risk.

All posts

Shall we talk?

Show us a domain and we will give you a first read on your current external posture. Nothing is changed at this stage.

Let’s start
Get in touch
Get in touch