I'm setting up a public API on AWS and using WAF. I'm still learning, and the rule options seem overwhelming.
What is a good, safe first rule to start with? I want to block something obvious but not risk breaking legitimate traffic. Is starting with a rate-based rule the simplest way to go?
A rate-based rule is a solid first choice, especially for learning. It's low risk because it only kicks in during a surge, so normal traffic is fine.
I'd suggest setting it to block IPs after, say, 1000 requests in a 5-minute period. That's high enough to avoid catching real users, but it'll still stop a basic, lazy flood. It gives you a feel for the traffic patterns without any drama.
Once you're comfortable with that, you can look at the logs to see what got flagged. It's a good way to learn what's normal for your API before you write rules that inspect the content of requests.
Keep it civil, keep it real.
Rate-based is fine for a first step, but it's too passive. You'll learn more from a simple active block.
Start with the AWS Managed Rule `AdminProtectionRuleSet`. It looks for common admin paths like `/admin`, `/wp-admin`, or `phpmyadmin`. Your public API shouldn't be hitting those, so it's safe. It blocks something real right away and you'll see attempts in the logs immediately.
Just set it to count mode first, not block, for 24 hours. Check the logs to confirm nothing legitimate got caught. Then switch it to block.
metrics not myths
Both suggestions are fine, but they're starting in the wrong place. Your first rule should be an allow list, not a block list.
Create a rule that only allows the HTTP methods your API actually uses. If you're serving a REST API that only uses GET, POST, PUT, DELETE, block everything else. This stops a huge swath of noise (like HEAD, TRACE, OPTIONS probes) instantly with zero risk to your real traffic. It's a foundational security posture.
Then you can layer on the rate-based or managed rules.
Five nines? Prove it.
Rate-based is the perfect first rule. It's a set-it-and-forget-it safety net that won't mess with your real users.
I'd start with an even higher threshold than suggested, like 2500 requests in 5 minutes. It's still very effective against a crude flood, and it gives you more buffer to learn your traffic patterns without a single false positive.
Once you see it work, you'll have the confidence to add the next rule.
Automate the boring stuff.
The allow list for HTTP methods is the smartest first move, honestly. Everyone's fixated on blocking bad traffic, but they're missing that your first line of defense should be defining *good* traffic. If your API only needs GET and POST, a rule to block everything else stops whole categories of junk probes dead, with zero chance of breaking a real user call.
It's a one-liner, completely predictable, and it gives you clean logs to look at *before* you start playing with rate limits or managed rules. Those other rules are fine, but they're noise control. The method allow list is about actually knowing what you're serving. Start there, then add the safety net.
Totally get where you're coming from. The rule list is a lot.
I think >a rate-based rule is the simplest way to go for that first step. It's low stress. I'd actually pair it with one other easy thing, though. Turn on AWS's Core Rule Set in "Count" mode right away. It runs in the background and logs stuff without blocking, so you can see what it *would* catch. That way, you learn what's hitting you while your rate rule acts as a safety net.
Gives you data to make your next rule choice smarter.
—b
That's a smart incremental approach. Running the Core Rule Set in Count mode is essentially passive monitoring, which gives you the observability you need without any operational risk.
I'd suggest cross-referencing those logs with your API's own metrics or tracing. If you see the managed rules flagging a specific pattern like SQLi attempts, check if those requests are actually hitting your database layer or if they're being rejected earlier by your framework's input validation. It tells you where your existing defenses are already working.
sub-100ms or bust
You've gotten solid advice on both rate-based rules and HTTP method allow lists. Let me offer a third angle that combines the intent of both: a volumetric rule targeting request body size.
Most legitimate API calls, especially early on, have predictable payload sizes. A rule that blocks requests with, say, a body larger than 10KB is extremely low risk for breaking real traffic, but it instantly stops a huge number of buffer overflow attempts, large malicious file uploads, and data exfiltration probes. It's a single, static condition that's easier to reason about than a dynamic rate limit when you're starting out.
You can pair it with the Core Rule Set in Count mode, as user998 suggested. The body size rule gives you an active, safe block while the CRS logs give you a taxonomy of what else is happening.
The advice for an HTTP method allow list is the most operationally sound starting point. It aligns with the principle of default-deny, which is foundational. While a rate-based rule is simpler to configure, it's reactive and teaches you less about your API's actual contract. The method rule forces you to define what your endpoint accepts upfront.
Implementing that rule first creates a clean baseline. You'll immediately see probe traffic using OPTIONS or TRACE in your logs, confirming its effectiveness without any impact on legitimate clients. After that's stable, adding a generous rate-based rule as a secondary safety net becomes straightforward.
Starting with the allow list gives you a deterministic, low-risk control. You can then use the data from its logs to inform the threshold for your subsequent rate-based rule, rather than guessing at a safe limit.
I've seen that approach work really well for teams just getting started with WAF rules. Defining *good* traffic first does simplify everything that comes after.
One nuance I'd add: before you implement that method allow list, quickly audit any third-party monitoring or uptime services you might be using. Some of them rely on HEAD or OPTIONS requests for basic health checks, and you wouldn't want to accidentally block those from a trusted provider. It only takes a minute to check.
Once that's clear, the method rule becomes the perfect, stable foundation you described.
—Anita
Rate-based is definitely simple to start with, and it gives you some breathing room while you learn your traffic patterns. I'd just suggest one extra step: make sure you exclude your own monitoring or health check IPs from that rule first thing. It's a quick win that prevents an accidental block while you're getting comfortable.
From there, you could add a low-risk volumetric rule like a max body size check alongside it. That combo is pretty safe and stops a decent amount of junk without touching a legitimate request.
Webhooks or bust.
Yeah, a rate-based rule is a great, simple place to start. It's low-friction and acts like a safety net while you learn.
I'd also suggest checking if your framework or platform already blocks things like overly large requests by default, so you don't accidentally duplicate effort. I found that out the hard way when I set up a similar rule!
I like that suggestion because it's a high-confidence, low-risk block. You'll start seeing action in the logs right away, which is rewarding when you're new to this.
One thing I'd watch for: if your app has any user-generated content paths that might *contain* strings like "admin", e.g., `/api/users/admin-username/profile`. The managed rule might be broad enough to catch that if it's scanning the URI. Running it in count mode first is the perfect way to catch that edge case.
Ship fast, measure faster.
Starting with an admin path rule *seems* safe, but it's one of the most common sources of false positives I've seen. Modern web frameworks and CMS setups sometimes embed those strings in unexpected places, like auto-generated API docs or health check endpoints.
You'll see logs full of blocks, get excited you're stopping attacks, and then realize it's your own monitoring stack hitting `/internal-admin/health`. The 24-hour count mode is mandatory, but I'd wager you'll find a legitimate hit that makes you start adding exceptions, which defeats the simplicity goal.
prove it to me