In brief: There is no single switch that stops DDoS. Instead, each layer should drop the traffic it can identify cheaply.
The problem
Application rate limiting kicks in too late for connection exhaustion and slow clients. But blocking everything at one layer is no better: it causes false positives and turns that layer into a new bottleneck.
Why the simple answer is not enough
DDoS is a problem of resource asymmetry. The attacker tries to turn each cheap request into expensive connection, CPU, memory or database work. A control placed only inside the application activates after most of that cost has already been paid.
Defence therefore needs decisions that grow richer at each layer. The edge sees network reputation and volume; the proxy controls connection behaviour; the application understands the account, the route cost and the business intent.
System flow
untrusted traffic→CDN or WAF
volumetric filtering→Reverse proxy
timeouts and IP limits→Application
route-aware limits
Architecture decisions
Drop traffic at the cheapest layer
Use an anycast CDN or managed scrubbing for volumetric attacks, WAF rules for known patterns, and origin allow-lists so attackers cannot slip past the edge and connect directly.
Budget connections and request bodies
At the reverse proxy, cap header and body sizes, header-read and idle timeouts, connections per source and concurrent requests. A slow client should never hold scarce origin sockets indefinitely.
Rate-limit by cost and identity
Group routes by cost, then combine account, API key, trusted proxy-derived IP and device signals. Login, search and report generation each need their own token cost and burst allowance.
Going deeper
Build controls from a threat model
Start by listing the resources an attacker can exhaust: bandwidth, TLS handshakes, sockets, request-body buffers, authentication hashing, cache misses, database queries and expensive business operations. Map each resource to the earliest layer that can protect it, and give it a measurable budget. Remember that IP alone is a weak identity behind carrier NAT, corporate proxies and IPv6 privacy addresses. Combine network signals with account, API key, device cookie and behavioural history. Keep the rules understandable enough that you can explain a block to support teams and legitimate customers.
Mitigation must be operable during an incident
Predefine severity levels, owners and reversible actions. A first stage might tighten anonymous bursts; later stages can challenge suspicious clients, disable costly endpoints or allow-list critical integrations. Configuration changes need versioning, peer review and automatic expiry, so an emergency rule does not become permanent technical debt. Preserve sampled evidence, but do not log sensitive request bodies. Incident dashboards should parse the trusted client IP the same way enforcement does; otherwise operators investigate different identities from the ones being limited.
Implementation path
- Let the CDN or WAF absorb volumetric traffic and known bad patterns.
- Set connection, body and idle timeouts at the reverse proxy.
- Apply per-endpoint-group limits before any expensive authentication or database work.
Technical example: Weighted token-bucket policy
policy['read'] = { rate: 60/min, burst: 30, cost: 1 }
policy['login'] = { rate: 10/min, burst: 5, cost: 3 }
policy['export'] = { rate: 2/min, burst: 1, cost: 20 }
identity = accountId ?? apiKeyId ?? trustedClientIp
bucket = `${routeGroup}:${identity}`
allowed = tokenBucket.consume(bucket, policy[group].cost)
if (!allowed) return 429 with Retry-AfterOnly accept forwarding headers from known proxies. Otherwise an attacker can rotate a forged client IP and defeat any limit that trusts X-Forwarded-For.
Failure modes to design for
- The origin DNS or IP stays public and bypasses the CDN. Restrict ingress to edge ranges, or require authenticated origin connections.
- The central rate-limit store fails. Choose fail-open for low-cost reads, and a bounded local fallback or fail-closed policy for expensive or security-sensitive routes.
- A legitimate campaign looks like an attack. Use staged mitigation, per-customer quotas and a documented emergency override with an expiry and an audit trail.
What to observe
| Signal | Why it matters |
|---|---|
| Edge accepted versus origin requests | Shows how much malicious volume is removed before it consumes origin resources. |
| Connections, handshake failures and timeouts | Surfaces connection exhaustion and slow-client attacks that request counters miss. |
| 429 rate by route and identity class | Tells an undersized quota apart from a concentrated abusive pattern. |
| Origin saturation and customer error rate | Confirms that mitigation protects availability instead of just moving failures onto valid users. |
How to validate the design
- Replay volumetric, connection-slowing and application-cost scenarios separately, because each stresses a different layer.
- Send legitimate burst profiles, such as login opening time, campaign traffic and partner batch integrations.
- Attempt direct origin access and spoofed forwarding headers from outside every trusted proxy range.
- Fail the distributed counter and verify that each route follows its documented fail-open, fallback or fail-closed policy.
- Measure the false-positive rate and the recovery time after limits are relaxed, not only the number of requests blocked.
Safe rollout plan
Deploy new rules in count-only mode first, and label the reason for each decision. Compare the projected blocks against authenticated customer traffic and known business events, then enforce for a small share, or only for clearly abusive thresholds, to begin with. Keep independent kill switches for the edge, proxy and application policies. Schedule a game day where the team raises severity, protects a simulated overloaded dependency, communicates the impact and restores normal thresholds. The goal is a response that can be repeated under pressure, not a pile of rules that only one engineer understands.
Production checklist
- Limits must leave room for legitimate bursts, such as login spikes or campaign traffic.
- Decide explicitly whether a failed counter fails open or fails closed.
- Watch rejected traffic, origin load and customer error rate together.
Takeaway
Layered defence lowers cost step by step and keeps the application available for legitimate users.
