---
title: How to Configure AWS WAF for API Protection (Beyond the Basics)
description: WAF beyond “enable managed rules”: COUNT→BLOCK, rate limits, Bot Control cost traps, GraphQL depth. July 2026 API protection checklist.
url: https://www.joinhorizon.co/blog/how-to-configure-aws-waf-api-protection-beyond-basics/
datePublished: 2026-04-03T00:00:00.000Z
dateModified: 2026-10-28T00:00:00.000Z
author: nash-ogden
category: Security & Compliance
tags: how-to-guide, waf, api-security, ddos-protection, aws, security
---

# How to Configure AWS WAF for API Protection (Beyond the Basics)

> WAF beyond “enable managed rules”: COUNT→BLOCK, rate limits, Bot Control cost traps, GraphQL depth. July 2026 API protection checklist.

AWS WAF protects APIs at Layer 7: SQLi, XSS, credential stuffing patterns, rate abuse, and (with Bot Control) many bot classes, before traffic hits your code. As of **July 2026**, the production pattern is still **managed rules + rate-based rules in COUNT first**, then BLOCK; treat **Bot Control / CAPTCHA / Challenge** as separately modeled cost lines (Common Bot Control has a free request tier; Targeted does not scale the same).

**First-party benchmark (illustrative):** enabling three managed rule groups + rate limits on ~100M req/mo is often ~low-hundreds USD/mo at list; flipping Targeted Bot Control + CAPTCHA on the same QPS without scoping can 2 to 5× that. Verify on the pricing page before “enable everything.”

**Reproduce this:** [WAF COUNT→BLOCK checklist](https://www.joinhorizon.co/examples/architecture-blog-2026/waf-api-protection/waf-api-count-to-block-checklist.md)

> **Securing APIs on AWS?** [Security services](https://www.joinhorizon.co/services/aws-cloud-security/) · [contact](https://www.joinhorizon.co/contact-us/).

## Step 1: Understand AWS WAF architecture

AWS WAF sits in front of your API (CloudFront, ALB, API Gateway, AppSync):

```
Client Request
  ↓
WAF Rules (check request)
  → Rule 1: Is SQL injection? → BLOCK
  → Rule 2: Rate limit? → BLOCK if >1000 req/min
  → Rule 3: Known bot? → BLOCK
  ↓ (if all rules pass)
API (protected)
```

**Key concepts:**

- **Web ACL**: Container for rules (like a security policy)
- **Rules**: Conditions that trigger actions (BLOCK, ALLOW, COUNT)
- **Managed Rules**: AWS-written rules for OWASP Top 10 (SQL injection, XSS, etc.)
- **Custom Rules**: Your own patterns (IP blocking, rate limiting, etc.)
- **Action**: What happens when a rule matches (BLOCK, COUNT, CHALLENGE)

## Step 2: Create a web ACL

Go to **AWS WAF & Shield** → **Web ACLs**:

1. Click **Create web ACL**
2. **Name**: `api-protection`
3. **Region**: Select region (WAF is region-specific; ALB needs same region)
4. **Associated resources**: Select API Gateway, ALB, or CloudFront
5. Click **Next**

## Step 3: Add AWS managed rules

AWS provides rule groups for common attacks. Add them:

1. Go to **Add rules** → **Add managed rule groups**
2. Enable:
   - **AWSManagedRulesCommonRuleSet** (SQL injection, XSS, etc.)
   - **AWSManagedRulesKnownBadInputsRuleSet** (known malicious payloads)
   - **AWSManagedRulesAmazonIpReputationList** (known bad IPs)

For each rule group, set **Action**:

- **Block**: Stop the request (recommended for production)
- **Count**: Log but don't block (use this first to validate)

Example rule: Block SQL injection attempts:

```
Rule: AWSManagedRulesSQLiRuleSet
Action: BLOCK
Status: Enabled
```

Click **Add rules**.

## Step 4: Add rate limiting

![Architecture diagram of a client over the rate limit blocked by an AWS WAF rate rule](../../assets/images/blog/how-to-configure-aws-waf-api-protection-beyond-basics-rate.webp)

_Figure: the rate-based rule in the article. A client over the limit is blocked at WAF and does not continue to the origin. The sample limit stays in the steps. Count mode is a different post. [Open the draw.io source](https://www.joinhorizon.co/examples/architecture-blog-2026/how-to-configure-aws-waf-api-protection-beyond-basics/rate.drawio)._

Prevent DDoS and brute force attacks:

1. Click **Add rules** → **Add my own rules**
2. **Rule name**: `rate-limit-per-ip`
3. **Type**: Rate-based rule
4. **Rate limit**: 2000 (requests per 5-minute period)
5. **Action**: BLOCK
6. Click **Create**

This blocks any IP sending >2000 requests in 5 minutes.

For API-specific rate limiting (per user/API key):

```
Rule name: rate-limit-per-api-key
Type: Rate-based rule with custom scope
Scope key: Header (X-API-Key)
Rate limit: 100 requests per minute
Action: BLOCK
```

## Step 5: Add custom rules for API protection

### Rule 1: Block large payloads

Prevent payload bombs:

```
Rule name: block-large-payloads
Conditions:
  - Body size > 10,000 bytes
  - HTTP method = POST
Action: BLOCK
```

### Rule 2: Require a Content-Type header

Prevent content confusion attacks:

```
Rule name: require-content-type
Conditions:
  - Header "Content-Type" is missing
  - HTTP method = POST or PUT
Action: BLOCK
```

### Rule 3: Block suspicious user agents

Block known bots and scrapers:

```
Rule name: block-bots
Conditions:
  - User-Agent matches (regex): .*bot.*|.*scraper.*|.*curl.*
Action: COUNT (first), then BLOCK
```

### Rule 4: Protect admin paths

Block access to internal endpoints:

```
Rule name: protect-admin-paths
Conditions:
  - URI path starts with /admin
  - IP is NOT in whitelist [10.0.0.0/8, 203.0.113.0/24]
Action: BLOCK
```

### Rule 5: Prevent credential stuffing

Detect login brute force:

```
Rule name: prevent-login-brute-force
Conditions:
  - URI path = /api/login
  - HTTP method = POST
  - Rate limit: 10 requests per minute per IP
Action: BLOCK
```

## Step 6: Test rules in COUNT mode

Before blocking, validate rules don't break legitimate traffic:

1. Set all rules to **COUNT** action
2. Run for 24-48 hours
3. Monitor CloudWatch logs for blocked requests
4. Check if legitimate requests are being matched
5. Adjust thresholds if needed
6. Switch rules to **BLOCK**

View logs in **CloudWatch** → **Log groups** → `/aws/wafv2/api-protection`:

```json
{
  "httpRequest": {
    "clientIp": "203.0.113.5",
    "userAgent": "curl/7.64.1",
    "uri": "/api/users/123",
    "httpMethod": "GET"
  },
  "action": "BLOCK",
  "terminatingRuleId": "rate-limit-per-ip",
  "timestamp": 1712145600000
}
```

## Step 7: Enable Bot Control (optional)

AWS Bot Control identifies and blocks malicious bots:

1. In Web ACL, click **Add rules** → **Add managed rule groups**
2. Enable **AWSManagedRulesBotControlRuleSet**
3. **Action**: BLOCK
4. Cost: $10/month per million requests

Bot Control categorizes traffic:

- **Verified bots**: Google, Amazon (allowed by default)
- **Suspicious bots**: Credential stuffing tools (blocked)
- **Crawler**: Search engine bots (allowed)

## Step 8: Monitor and alert

![Architecture diagram of an AWS WAF web ACL sending blocked-request counts to a CloudWatch alarm](../../assets/images/blog/how-to-configure-aws-waf-api-protection-beyond-basics-alarm.webp)

_Figure: monitoring in the article. The web ACL publishes the blocked-request count, and the alarm fires on that count. The article's dashboard and log steps stay in the post. No threshold on the figure. [Open the draw.io source](https://www.joinhorizon.co/examples/architecture-blog-2026/how-to-configure-aws-waf-api-protection-beyond-basics/alarm.drawio)._

### CloudWatch dashboard

Create a dashboard to monitor attacks:

```python
import boto3

cloudwatch = boto3.client('cloudwatch')

cloudwatch.put_metric_alarm(
    AlarmName='WAF-SQL-Injection-Detected',
    MetricName='BlockedRequests',
    Namespace='AWS/WAFV2',
    Statistic='Sum',
    Period=300,
    Threshold=10,
    ComparisonOperator='GreaterThanThreshold',
    AlarmActions=['arn:aws:sns:us-east-1:123456789012:security-alerts']
)
```

### Log analysis

Query WAF logs for attack patterns:

```python
import boto3
from datetime import datetime, timedelta

logs = boto3.client('logs')

response = logs.start_query(
    logGroupName='/aws/wafv2/api-protection',
    startTime=int((datetime.now() - timedelta(hours=1)).timestamp()),
    endTime=int(datetime.now().timestamp()),
    queryString='fields @timestamp, action, terminatingRuleId | stats count() by terminatingRuleId'
)

print(response['queryId'])
```

## Step 9: Advanced patterns

### Pattern 1: IP reputation scoring

Combine multiple signals to build IP reputation:

```
Rule: IP Reputation Score
Conditions:
  - Source IP in AWSManagedRulesAmazonIpReputationList
  - OR Request rate > 500 per minute
  - OR User-Agent is known bot
Action: CHALLENGE (CAPTCHA)
```

Challenge (CAPTCHA) instead of block for borderline cases (suspicious but not confirmed malicious).

### Pattern 2: Geo-blocking

Block traffic from specific regions (if needed for compliance):

```
Rule: Geo-block
Conditions:
  - GeoLocation is China, Russia, Iran
Action: BLOCK
```

Use for regulated industries (healthcare, finance) if needed.

### Pattern 3: API key validation

Use WAF to validate API keys before reaching app:

```
Rule: Invalid API Key
Conditions:
  - Header "X-API-Key" is missing
  - OR Header "X-API-Key" does NOT match regex ^[a-zA-Z0-9]{32}$
Action: BLOCK
```

This catches malformed keys before app processing.

## Step 10: Production checklist

- [ ] Managed rule groups enabled (SQLi, XSS, bad inputs)
- [ ] Rate limiting configured (2000 req/min per IP)
- [ ] Large payload blocking enabled (>10KB)
- [ ] Content-Type validation enabled
- [ ] Bot blocking enabled (or COUNT mode)
- [ ] All rules tested in COUNT mode (24+ hours)
- [ ] Alarms configured for spike in blocked requests
- [ ] Team trained on incident response (what to do if WAF is blocking good traffic)
- [ ] Logging enabled to CloudWatch
- [ ] Weekly review of blocked requests (identify false positives)

## Common mistakes to avoid

1. **Blocking legitimate traffic**
   - Don't start with BLOCK immediately
   - Use COUNT mode first, monitor for 48 hours
   - Increase thresholds if legitimate traffic is blocked

2. **Too-broad IP blocking**
   - Blocking entire country = blocks VPNs, proxies, legitimate users
   - Use for specific IPs, not ranges (unless critical)

3. **No alerting**
   - 10,000 blocked requests = major attack
   - Set up CloudWatch alarms to notify on spike

4. **Ignoring false positives**
   - WAF blocks legitimate request once per month
   - Review logs weekly, adjust rules if pattern emerges

5. **Forgetting to scale rate limits**
   - Set limit to 2000 req/min, API grows to 5000 req/min
   - Legitimate traffic gets blocked
   - Monitor max legitimate request rate, set limit 2-3x higher

## Cost optimization

Verify current numbers on [AWS WAF pricing](https://aws.amazon.com/waf/pricing/). Budget separately for:

- Web ACL + custom rules + managed rule groups (monthly, prorated)
- Request volume (and WCU / body inspection overages if you exceed defaults)
- Bot Control (Common vs Targeted free tiers differ)
- CAPTCHA attempts / Challenge responses when those actions fire

**Counter-case:** enabling Targeted Bot Control + CAPTCHA on every path “for safety” is how WAF becomes a surprise bill. Scope Bot Control to login/checkout/GraphQL first.

## What this post doesn't cover

Shield Advanced DRT process and account-level Firewall Manager multi-account rollout are covered in the production WAF and Shield buyer guides.

## What to do Monday morning

1. Create/attach one Web ACL; put AWS managed rule groups in **COUNT**.
2. Add rate-based rules on login and expensive routes; COUNT 48h.
3. Review logs; flip BLOCK rule-by-rule; alarm on BlockedRequests spikes.
4. Walk the [COUNT→BLOCK checklist](https://www.joinhorizon.co/examples/architecture-blog-2026/waf-api-protection/waf-api-count-to-block-checklist.md).
5. Next: [WAF production guide](https://www.joinhorizon.co/blog/aws-waf-web-application-firewall-production-guide/) · [cost-based attacks](https://www.joinhorizon.co/blog/protect-aws-infrastructure-cost-based-attacks/).
6. [Talk to FactualMinds](https://www.joinhorizon.co/contact-us/) · [security services](https://www.joinhorizon.co/services/aws-cloud-security/).

## FAQ

### What attacks does AWS WAF actually prevent?
AWS WAF prevents: (1) SQL injection ("admin'--"), (2) Cross-site scripting (XSS) (`<script>alert(1)</script>`), (3) Path traversal (../../../etc/passwd), (4) DDoS: rate-based rules block >1000 req/min from same IP, (5) Bot attacks: identifies scrapers and credential stuffing, (6) Account takeover: detects unusual login patterns. What WAF does NOT prevent: business logic bugs, insecure API design, weak authentication. WAF is one layer; you still need secure code.

### How much does AWS WAF cost?
Base WAF charges for each web ACL, each rule/rule group, and requests processed, plus optional Bot Control, CAPTCHA, and Challenge. List prices change; verify aws.amazon.com/waf/pricing. Directionally, a single Web ACL with a few managed rule groups on tens to hundreds of millions of requests/month is often low hundreds of dollars, but Targeted Bot Control + CAPTCHA on a high-QPS API can dominate. Always COUNT for 48h before BLOCK, and model Bot Control before enabling it on every path.

### Can AWS WAF block legitimate requests?
Yes, if rules are too aggressive. Example: a rule blocking all POST requests with >1000 characters blocks legitimate large payloads (file uploads, JSON bodies). Solution: (1) Use COUNT mode first to see what gets blocked without actually blocking, (2) Whitelist legitimate patterns (e.g., allow Content-Type: application/json), (3) Set high thresholds initially, lower if needed, (4) Test with real traffic in staging.

### How do I protect a GraphQL API with WAF?
GraphQL is trickier than REST because malicious queries look like legitimate requests. WAF rules: (1) Depth limiting: block queries with >10 nested fields (detects introspection attacks), (2) Query size limiting: block >10KB payloads, (3) Rate limiting per API key (GraphQL queries can be expensive), (4) Whitelist known queries (if API is semi-public), (5) Use Apollo Server rate limiting in app layer too (defense-in-depth). WAF alone isn't enough for GraphQL; add application-level protection.

### What is the difference between WAF and Shield?
AWS Shield (free) provides basic DDoS protection at Layer 3/4 (network-level attacks). AWS WAF (paid) adds Layer 7 (application-level) protection. Example: (1) Attack: 10 Gbps of traffic floods your IP. Shield stops it at network level. (2) Attack: 1M requests/min with malicious payloads. WAF blocks at application level. Use both: Shield + WAF for comprehensive protection. Shield Advanced ($3,000/month) includes DDoS response team; for most startups, free Shield + WAF is sufficient.

---

*Source: https://www.joinhorizon.co/blog/how-to-configure-aws-waf-api-protection-beyond-basics/*
