After deploying Cloudflare's Managed Ruleset in its default configuration, our initial false positive rate was unacceptable for production traffic—approximately 15% of total requests were being challenged. This analysis covers a 30-day tuning period for a mid-sized SaaS application handling ~2M requests daily.
The primary adjustment was moving from a **block** to a **score-based** action for most rules. We used the Cloudflare Security Analytics dashboard to identify the top offending rules. The most significant contributors were:
- **Managed Rule 100043** (PHP Injection Attacks): 40% of initial FPs
- **Managed Rule 100030** (SQLi Detection): 25% of initial FPs
- **Managed Rule 100015** (Cross-site Scripting): 15% of initial FPs
We implemented a three-phase tuning workflow:
1. **Log-Only Phase (7 days):** All rules set to `log`. Exported logs to BigQuery for pattern analysis.
2. **Scoring Phase (14 days):** Applied `score` actions with thresholds. Example configuration snippet for a rule override:
```json
{
"id": "100043",
"action": "score",
"score_threshold": 10
}
```
3. **Final Deployment (7 days):** Moved validated rules to `block`, kept others in `managed_challenge`.
**Results:**
- Baseline FP rate: ~15% (300k requests/day)
- Post-tuning FP rate: ~3% (60k requests/day)
- **Reduction: 80%**
- No increase in verified malicious requests bypassing the WAF (monitored via external penetration test reports).
Key finding: The default block thresholds are aggressive for applications with complex query parameters or legacy API formats. The `score` action is critical for gradual tuning without disrupting legitimate traffic. The Security Analytics interface, while sometimes slow for large datasets, provided the necessary granularity to make data-driven decisions.
Numbers don't lie
Moving to a score-based system was the key for us too. That initial log-only phase is painful but you can't skip it - we found a few legitimate admin tools triggering the PHP rule because of how they passed configuration arrays.
What threshold did you settle on for rule 100030? We had to go as low as 8 before our batch job queries stopped getting flagged, which felt risky but the analytics backed it up.
Are you planning to keep the managed_challenge actions long-term, or will you iterate further toward block? I'm always torn between user friction and closing the loop.
Ship fast, measure faster.
Yeah, the admin tool angle is a great point. We had a similar issue with our internal monitoring pings - they looked like encoded attacks but were just poorly formatted health checks.
For 100030 we actually landed on a threshold of 10. Setting it to 8 felt a bit too loose for our comfort, but we ended up creating a specific bypass for that one batch job's user agent instead. It felt cleaner than lowering the security for everything.
On the managed_challenge vs block question, I'm leaning towards keeping the challenge for now. The friction is minimal for real users, and it still catches the blatant stuff. I still see the occasional attempted probe that gets a challenge and just disappears, which feels like a win. Are you seeing many challenges turn into successful blocks?
Always testing.