Bunny Shield WAF: fast, flexible, and RegEx-ready

Posted by:

RegEx rules unlock precise control: you can match exactly what you want and ignore what you don’t. But if you’ve ever worked with regular expressions at scale, you know the risks, including slowdowns, CPU spikes, and even full-blown outages when something goes wrong.

So we built something better. A WAF engine that hops circles around traditional RegEx bottlenecks.

In this post, we’ll walk you through how we made it fast, why it matters, and what it unlocks for builders like you. Whether you're fighting fraud, shaping traffic, or crafting defenses against complex attacks, you now have full control with none of the lag.

Why custom RegEx rules matter (and why they’re hard)

Sometimes the built-in rule presets just aren’t enough.

Maybe you need to:

  • Block a specific user-agent pattern used by a malicious toolset
  • Detect suspicious access to versioned endpoints like /v1/private or /v3/internal
  • Throttle behavior based on header combinations only you know indicate abuse

That’s where custom RegEx rules shine. They let you go beyond checkboxes and dropdowns. They give you control.

But there’s a catch.

Traditional RegEx processing is slow. It’s notoriously vulnerable to “catastrophic backtracking” and RegEx-based denial-of-service (ReDoS) attacks. Naively executed rules can eat up CPU, introduce latency, or worse, block legitimate traffic if they time out under load.

That’s why, when it comes to custom RegEx rules, many platforms play it safe:

  • Limiting what users can write: no lookaheads, no nested groups, and strict pattern rules
  • Offloading matching to slower, less performant processing queues
  • Avoiding user-defined RegEx support altogether

That wasn’t good enough for us.

Inside the engine: fast, safe RegEx at the edge

RegEx is a powerful tool, but it comes with sharp edges.

Under the hood, most RegEx engines work by backtracking through possible matches. That’s fine for simple patterns. But if a pattern includes nested quantifiers, wildcards, or poorly anchored alternation, it can cause the engine to spiral into catastrophic backtracking, consuming CPU and hanging processes, especially on long or crafted inputs.

This isn’t just theoretical. We’ve seen it firsthand: a seemingly harmless ^.*a.*$ pattern brought one edge server to a crawl after being fed a long string with thousands of repeating characters.

To solve this, many platforms take the safe route. They limit what kinds of RegEx you can write. No nested groups. No lookaheads. No backreferences. That avoids the danger, but it also blocks a lot of real-world use cases.

We wanted to do better.

Enter .NET's modern RegEx engine

In recent years, .NET introduced a non-backtracking RegEx engine: a safer, more deterministic approach that compiles patterns into a state machine and guarantees linear-time execution.

It’s great for complex or risky patterns but comes with a tradeoff. On simple expressions, it can be slower than the classic engine. It also doesn’t support some advanced features like backreferences or certain types of look-behinds.

So rather than picking one engine and hoping for the best, we built an adaptive decision layer.

// Long patterns? Use non-backtracking. if (pattern.Length > 100) return true; // No special characters? Use default. if (!pattern.AsSpan().ContainsAny(SpecialCharacters)) return false; // Check for nested quantifiers. var depth = 0; var hasQuantifierInGroup = false; for (var i = 0; i < pattern.Length; i++) { switch (pattern[i]) { case '(': if (hasQuantifierInGroup) return true; depth++; break; case ')': depth--; if (i + 1 < pattern.Length && pattern[i + 1] is '*' or '+' or '{') hasQuantifierInGroup = true; break; case '*' or '+' or '{': if (depth > 0) return true; break; } } // Alternation with quantifiers? Risky. return hasQuantifierInGroup && pattern.Contains('|');

Memory-safe rule processing that scales

Compiling RegEx is expensive, so we cache compiled patterns for reuse. But naïve caching introduces another problem: memory leaks. Over time, especially with rotating rule sets, patterns can accumulate in memory, even if they’re no longer used.

To fix this, we moved from a persistent dictionary to a smarter system using ConditionalWeakTable , a memory-aware structure that keeps things cached only as long as they're in use and lets the garbage collector safely clean up the rest. We also built a lightweight string interning system that deduplicates repeated rule patterns automatically.

The result is a system that’s not just fast, but safe, lean, and long-term stable, even for high-traffic websites or services running hundreds of custom rules.

Benchmarks: built for performance

We benchmarked our WAF engine using a realistic configuration that reflects common high-traffic production environments. The test scenario included:

  • A typical number of headers
  • A JSON response body returned from the origin
  • 10 custom WAF rules, each using the RX (RegEx) operator
  • 495 top-level WAF rules evaluated per request (excluding chained sub-rules)
  • Detection paranoia level set to 4 for GET requests and 1 for POST with JSON payloads

This setup gives us a clear baseline for edge performance under practical, real-world load.

AMD Ryzen 7 5800X, 1 CPU, 16 logical and 8 physical cores [Host] : .NET 8.0.15 (8.0.1525.16413), X64 RyuJIT AVX2 Job-PRISSO : .NET 8.0.15 (8.0.1525.16413), X64 RyuJIT AVX2 Server=True InvocationCount=4000 IterationCount=15 | Method | Mean | Error | StdDev | Gen0 | Allocated | |----------|---------:|---------:|---------:|-------:|----------:| | Get | 354.1 us | 10.93 us | 10.22 us | 0.2500 | 124.42 KB | | PostJson | 578.0 us | 13.17 us | 10.28 us | 0.5000 | 159.02 KB |

Catastrophic backtracking? Defused.

To demonstrate just how dangerous bad RegEx can be, and how Bunny Shield avoids it, we benchmarked a worst-case input against a seemingly harmless pattern: ^([a-zA-Z0-9]+\.?)+@([a-zA-Z0-9]+\.?)+$

BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.3775) AMD Ryzen 7 5800X, 1 CPU, 16 logical and 8 physical cores [Host] : .NET 8.0.15 (8.0.1525.16413), X64 RyuJIT AVX2 ShortRun : .NET 8.0.15 (8.0.1525.16413), X64 RyuJIT AVX2 Job=ShortRun Server=True IterationCount=3 LaunchCount=1 WarmupCount=3 | Method | Input | Mean | StdDev | Allocated | |---------------- |--------------------- |---------------:|------------:|----------:| | PCRE2 w/ limit | aaaaaaaaaaaaaaaaaaa@ | FAIL | FAIL | FAIL | | PCRE2 unlimited | aaaaaaaaaaaaaaaaaaa@ | 2,289,122.5 ns | 8,607.43 ns | 158 B | | .NET NBT | aaaaaaaaaaaaaaaaaaa@ | 111.6 ns | 0.08 ns | - |

That means you can write precise, expressive rules without fearing performance penalties. This is where Bunny steps in, handling complexity without missing a hop.

Real-world rule ideas: what you can build

Your traffic isn’t one size fits all. Bunny Shield Advanced ensures your rules don’t have to be either. Here are a few ways to make them your own:

Header-based blocking:

Path-based filters:

RegEx-based throttling:

Just simple, expressive rules. And complete control, on your terms.

Why this lives in advanced

We designed Bunny Shield Basic to be safe by default, with smart, managed rules that protect the majority of websites with zero config.

Whether you're scaling, handling abuse, or defending critical APIs, Bunny Shield Advanced is where that power lives.

You get:

  • 10 custom WAF rules and an increased number of rate limit rules
  • Full RegEx support with high-performance processing
  • Integrated bot and IP reputation filtering
  • White-label challenge pages
  • And more

All for $9.50/month. No sales call. No asterisk.

Security that doesn’t make you choose.

Modern attacks aren’t just louder, they’re more complex, distributed, and adaptive. Traditional WAFs struggle to keep up, either slowing things down or locking users into rigid, one-size-fits-all rules.

With Bunny Shield, we've set out to change that.

We designed it to give you fast, flexible protection that keeps up with real-world threats, without compromising performance or developer control. At bunny.net, performance is at the core of everything we do, and ensuring you stay safe online was no exception.

Write the rules your traffic demands, and we'll make sure your services stay fast, efficient, and light on their paws, regardless of what's thrown your way.

Hop into your dashboard and give your edge the fast, flexible defenses it deserves.