How DDoS Mitigation Actually Works
Try the interactive lab for this articleTake the quiz (6 questions · ~5 min)Most people talk about DDoS mitigation as if it were one box in front of a website. Traffic arrives, the box decides what looks bad, and the problem goes away.
That description is wrong in almost every interesting way.
A distributed denial of service attack is not one mechanism. It is a family of capacity attacks that try to make the defender spend scarce resources faster than legitimate users do. Sometimes the scarce resource is raw bandwidth on the public edge. Sometimes it is packets per second on a NIC, state in a firewall or load balancer, TLS handshake CPU, queue depth inside a reverse proxy, or expensive work in the application and database. Different attack shapes target different bottlenecks. Different mitigations restore different kinds of asymmetry.
This is why effective DDoS defence looks more like traffic engineering and admission control than like a single security feature. Operators spread ingress across many points of presence, validate that a sender can really receive replies, drop obviously fake traffic before allocating state, divert suspicious flows into scrubbing pipelines, cache and challenge at the edge, hide the origin, and prioritise the work that actually matters. None of those layers is sufficient alone. Together they buy time and preserve service.
The details matter because the internet is full of partial truths. Anycast helps, but it does not make capacity infinite. Scrubbing helps, but it can still block legitimate users if the policy is crude. SYN cookies help, but they do not solve application-layer floods. Rate limiting helps, but only if it is attached to the right identity and the right cost model. The mechanism is layered because the attack surface is layered.
DDoS Mitigation Starts By Asking Which Resource Dies First
The phrase "we are under DDoS" hides an important diagnostic question: what exactly is saturating?
Four common budgets fail in very different ways:
- Bits per second. The access link or upstream transit path fills before the application sees the traffic.
- Packets per second. Small packets can overwhelm NIC interrupt handling, forwarding silicon, conntrack lookups, or software firewalls long before the link is full.
- Connection or handshake state. A flood of half-open TCP handshakes, QUIC Initial packets, or proxy connection attempts can exhaust memory, queues, or CPU.
- Work per request. A relatively small number of valid-looking HTTP requests can trigger expensive cache misses, searches, renders, or database lookups.
Those ceilings are not interchangeable. A service can survive 80 Gbps of cached static traffic and fail under 2 Gbps of expensive authenticated search requests.
Consider a realistic public API fronted from Frankfurt and Amsterdam:
- 2 x 10 Gbps public edge links per site
- one TLS termination tier that can sustain about 65,000 handshakes per second per site before p95 latency rises sharply
- a reverse proxy layer that can keep 1.8 million mostly idle keepalive connections, but only a fraction of that if every connection constantly opens new streams
- a search backend that can safely process about 9,000 expensive uncached queries per second
An operator who only watches bandwidth will miss three other ways to lose.
The packet budget is especially misunderstood. Line rate and packet rate are related, but they are not the same pressure. Minimum sized packets are brutal because the per-packet overhead dominates. On 10 GbE, minimum Ethernet frames can drive roughly 14.88 million packets per second on one interface. A flood made of tiny UDP or SYN packets can therefore melt the edge far below the dramatic multi-hundred-gigabit numbers people associate with DDoS headlines.
A rough planning formula is:
pps ≈ bits_per_second / ((frame_bytes + l2_overhead) * 8)The exact overhead depends on what you count, but the planning lesson is stable: tiny packets turn line cards, software queues, and conntrack tables into the bottleneck much earlier than large packets do.
Application capacity has the same shape problem. Suppose a normal GET /catalog page hit is served from the edge cache in a few milliseconds. Now compare that with POST /search that triggers authentication, Elasticsearch fan-out, ranking, and a personalisation lookup. One request is almost free after the cache warm-up. The other spends CPU, heap, backend sockets, and often money on downstream services. Under attack, those requests cannot be defended with the same policy just because they are both HTTP.
The first real step in DDoS mitigation is therefore not "enable protection". It is making the budget visible. Mature teams baseline at least these dimensions:
- ingress Gbps by service and PoP
- ingress Mpps by service and PoP
- new connection rate or handshake rate
- conntrack, SYN backlog, and proxy queue occupancy
- cache hit ratio and cache bypass share
- per-route request rate and per-route backend cost
- TLS handshake CPU and termination latency
- origin error rate and tail latency
If you cannot tell which budget is failing first, you will deploy the wrong fix and call the attack mysterious.
Attack Families Exploit Different Asymmetries
The phrase DDoS covers several attack families that stress the defender in different ways.
| Attack family | Attacker spends | Defender loses | Classic examples | Typical first response |
|---|---|---|---|---|
| Reflection and amplification | small spoofed queries | bandwidth and packet budget | DNS amplification, NTP monlist, CLDAP, memcached | stateless filters, scrubbing, source validation upstream |
| State exhaustion | forged or incomplete handshakes | SYN backlog, conntrack, proxy state, TLS CPU | TCP SYN flood, QUIC Initial flood | SYN cookies, Retry, queue hardening, early drop |
| Application-layer flood | valid protocol traffic | expensive request work and backend concurrency | login floods, search floods, cache bypass, HTTP/2 abuse | caching, challenges, per-route admission control |
Reflection and amplification attacks work because the attacker tricks a third party into sending a much larger response at the victim. The attacker sends a small request with the source IP forged as the victim. An open resolver, NTP server, CLDAP endpoint, SSDP device, or badly exposed memcached service sends the reply to the victim, not to the real sender. If the reply is much larger than the request, the attacker has bought traffic amplification.
The key formula is simple:
amplification_factor = bytes_sent_to_victim / bytes_sent_by_attackerIf a 60-byte request causes a 3,000-byte response, the attacker multiplied their own outbound bandwidth by roughly 50. The entire trick depends on source spoofing still being possible somewhere on the network. Source validation practices such as BCP 38 and uRPF reduce that surface, but the public internet is not uniformly clean, so reflection remains operationally relevant.
The public record gives clear examples. The 2018 memcached reflection attack against GitHub was publicly reported at about 1.35 Tbps. The 2016 Mirai attack against Dyn did not rely on reflection in the same way, but it showed how a botnet of compromised IoT devices could directly flood a major DNS provider hard enough to make large parts of the web appear offline. In both cases the target was not only the application. The target was the capacity envelope around it.
State exhaustion attacks are different. Here the attacker is not trying to maximise bytes on the wire. They are trying to make the defender allocate per-flow work. The classic SYN flood sends large volumes of TCP SYN packets and never completes the three-way handshake. A naive server would allocate memory for every half-open connection and eventually run out. QUIC shifts the details, but not the core asymmetry. A flood of QUIC Initial packets can force the server to do cryptographic and parsing work before it knows the sender is real.
Application-layer floods exploit a third asymmetry: the requests can be semantically valid. The packets are well-formed, the TCP handshake completes, TLS looks normal, and the HTTP requests may resemble a browser. The damage comes from what the server does next. A cache-busting GET flood, an expensive GraphQL query set, or a login storm aimed at password hashing and database reads can be devastating even at modest bandwidth.
This is why large attacks are often multi-vector. An operator may see UDP reflection toward the public edge, SYN pressure on fallback IPs, and then a lower-bandwidth HTTP flood once the attacker notices the first two vectors are being filtered. The point is not elegance. The point is forcing the defender to spend attention and capacity in several places at once.
Middleboxes And Shared Infrastructure Often Fail Before The Application Notices
When engineers picture a DDoS event, they often imagine packets striking the application directly. Real failures are usually more indirect. The flood first meets routers, firewalls, conntrack tables, L4 load balancers, TLS terminators, reverse proxies, and queueing layers. One of those shared components often fails before the business logic even sees the request.
That matters because each middlebox has its own state model.
- a router may be fine on bandwidth and fail on packet rate
- a firewall may be fine on normal traffic and fail when every packet requires conntrack lookup
- a load balancer may be fine on established flows and fail on new connection churn
- a TLS proxy may be fine on reused sessions and fail on handshake CPU
- a reverse proxy may be fine on cached reads and fail on header parsing, body buffering, or upstream queue growth
The application team can look at dashboard graphs and say "the app is barely doing anything" while the public edge is already collapsing.
Linux conntrack is a common trap. Operators enable stateful firewalling or NAT because it is useful on ordinary days. Under a UDP flood or SYN storm, the table can fill with entries that are short-lived individually but enormous in aggregate. Once the table is full, legitimate flows start failing for reasons that look random to users. New sessions time out. Existing connections flap when related paths need fresh state. On a shared edge, one attacked service can therefore degrade unrelated tenants that happen to traverse the same state table.
This is why teams watch counters such as nf_conntrack_count, nf_conntrack_max, SYN backlog occupancy, accept queue saturation, and new-flow drop rate during incidents. Those numbers reveal whether the real bottleneck is the application or the machinery that merely stands in front of it.
Shared proxy fleets create a different failure mode. Modern reverse proxies are extremely capable, but they are not free. Every new connection needs some combination of socket allocation, timer state, header parsing, request classification, logging, compression decisions, and upstream routing. If the proxy tier is shared across many hostnames, a flood aimed at one hostname can steal CPU cache, file descriptors, and worker attention from every other hostname on the same fleet. The backend microservices may still be healthy. The shared front door is not.
Health checks can make this worse. Imagine a proxy tier in Warsaw that is already under handshake pressure. Backend health checks start timing out because the proxy workers are busy, not because the backends are actually broken. The control plane sees failing health checks and drains healthy backends. Traffic then shifts to fewer instances, increasing queue time and causing more health-check failures. The feedback loop looks like an application outage, but the initiating cause was edge contention.
Autoscaling is not a universal answer either. Capacity systems react on some time window. DDoS traffic can arrive faster than new instances, new virtual NICs, or new load balancer slots become useful. Even when scaling succeeds, the attacker may simply force the defender into a more expensive steady state. More proxies, more TLS workers, more log volume, and more cache churn can all be forms of attacker-imposed cost.
The path through middleboxes also changes what mitigation is rational. If the firewall is the first thing failing, pushing more complex rules into that same firewall is self-defeating. If the TLS terminator is saturated, more application logic behind it is irrelevant until handshake work is reduced. If a shared L7 proxy is the choke point, isolating critical hostnames onto a narrower fleet may preserve revenue even if less important services degrade.
A healthy design therefore asks where state is created and whether that state is truly needed yet. The usual direction of improvement is:
- keep the first public layers as stateless as possible
- separate cheap packet screening from expensive protocol handling
- isolate critical services from bulk or low-value services when they do not need the same edge fleet
- avoid sharing one fragile conntrack or proxy layer across everything that has a public IP
- measure queue growth and rejection causes, not just successful request counts
This is also why some providers distinguish between packet filters, DDoS appliances, L4 proxies, and full HTTP proxy products. They are not interchangeable products with different logos. They create and consume state at different points in the path.
Once you see the middleboxes as possible victims, a lot of strange incident behaviour becomes easier to explain. Why did the origin CPU stay low while the site timed out? Because the SYN backlog or conntrack table died first. Why did only some regions fail? Because one metropolitan edge or one upstream-specific path hit its packet-rate ceiling first. Why did one product hostname survive while another fell over? Because their traffic reached different proxy pools with different cacheability and different handshake reuse.
The practical lesson is blunt: every shared network or proxy layer in front of the application is itself part of the attack surface. DDoS mitigation is not only about protecting the app from the internet. It is about protecting the internet-facing control and data path from being turned into the outage.
Anycast Changes The Geometry Before It Changes The Filter
Anycast is one of the most important DDoS tools because it changes where traffic lands before the mitigation policy ever sees a packet.
The mechanism is routing, not application logic. The operator advertises the same service prefix from many PoPs. Global BGP policy then causes clients to reach the topologically nearest or otherwise preferred site for that prefix. A user in Lisbon may land in Madrid or Paris. A user in Athens may land in Athens or Frankfurt depending on peering. The same is true for attack traffic.
For normal traffic, this reduces RTT and keeps the first public hop close to the user. Under attack, it spreads the flood across a wider surface.
Suppose a service advertises the same edge address from 60 PoPs and receives 1.2 Tbps of attack traffic. If the spread were perfectly even, each site would absorb 20 Gbps. Real routing is never that neat, but the arithmetic shows why anycast matters. A single-site service facing 1.2 Tbps is simply offline. A multi-site anycast fleet turns one catastrophic bottleneck into many smaller bottlenecks that can be filtered locally, shifted by route changes, or absorbed by overprovisioned edges.
This does not make capacity infinite. Anycast has hard limits:
- traffic distribution is uneven because the internet is policy-driven, not geography-driven
- some ISPs send disproportionately large shares into one metro or one upstream
- packet-per-second hot spots can appear even when aggregate Gbps looks comfortable
- a PoP can be healthy for users in one network and overloaded for users in another
- a route withdrawal solves one problem while increasing load elsewhere
In practice, a DDoS-resilient anycast network needs more than a shared prefix. It needs health-aware advertisement policy, spare headroom in several metros, visibility into per-PoP packet rate, and the ability to steer specific customer prefixes or tunnel endpoints into deeper mitigation when one region gets ugly.
This is also why people blur the line between a CDN and a DDoS network. Large CDNs are often a strong first layer of DDoS defence because they already have:
- many edge PoPs
- anycast ingress
- L4 and L7 proxy fleets
- caching to absorb cheap content
- customer-specific control planes for steering and policy
But anycast alone is not the defence. It is the force multiplier that makes the later defences economically possible. If the attack can be spread across Amsterdam, Frankfurt, Paris, Milan, Warsaw, and Madrid, then each site only needs to inspect its share. If everything lands on one origin prefix in one region, no amount of elegant application logic will save the link.
There is a second reason anycast matters. It reduces time-to-recovery for edge failures. If a PoP or transit path becomes unhealthy, the route can be withdrawn and traffic shifts to other sites without changing the client-visible address. During a live DDoS event, that operational agility is often as important as the raw capacity number.
First-Pass Defence Must Be Cheaper Than The Attack
The first filtering layer has one job: discard obviously bad traffic before the defender commits expensive state.
This sounds trivial. It is not. If your protection pipeline performs deep inspection, connection tracking, TLS parsing, or complex rule evaluation on every packet before deciding to drop, the attacker has already won part of the economic fight.
The early layers therefore tend to be deliberately simple:
- hardware ACLs in switches and routers
- stateless filtering in XDP, eBPF, or SmartNIC paths
- per-packet sanity checks on headers and flags
- SYN cookies for TCP handshakes
- QUIC Retry or other address-validation steps
- strict UDP policy for services that do not need public UDP at all
A classic TCP hardening set on Linux might include controls like these:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 262144
net.core.somaxconn = 65535
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 20Those are not magic values and they are not sufficient alone, but the direction is right. The defender is trying to keep handshake pressure from turning immediately into long-lived kernel state.
SYN cookies are a good example of restoring asymmetry. Instead of storing full half-open connection state for every SYN, the server encodes enough information into the SYN-ACK sequence number to validate the returning ACK later. That means the server can prove the client completed the return path without holding per-client memory for every bogus attempt. There are tradeoffs and implementation details, but the strategic value is clear: less state committed before proof.
QUIC has a similar need, even though the protocol is different. A server that receives large volumes of Initial packets may need to parse frames and derive keys just to decide what to do. Retry tokens and address validation move the trust boundary outward. A sender that cannot receive the token back is probably spoofed or at least not worth expensive work yet.
For reflection-style UDP floods, the cheapest useful filters are often based on traffic shape and policy, not on complex content understanding. If a customer service should only accept HTTPS on 443 and no public UDP, then huge bursts of UDP from common reflector source ports are easy to classify as junk. If a prefix is suddenly receiving vast DNS-sized responses even though the customer does not run a public DNS service there, the defender does not need philosophical certainty before dropping or diverting.
At the edge, operators often encode this principle almost as pseudocode:
if service_does_not_expect_udp and packet.protocol == UDP:
drop
if tcp.syn and return_path_not_validated:
use_cookie_or_challenge
if source_prefix_is_obviously_bogus:
drop
if packet_matches_known_reflection_signature:
divert_to_scrubbingThe exact implementation may live in router silicon, an XDP program, a DPU, or a userspace mitigation system, but the design rule is stable: spend nanoseconds before milliseconds, spend stateless checks before stateful checks, and spend the application as late as possible.
Scrubbing Centres Classify Flows And Tunnel Clean Traffic Back
Once the traffic exceeds what cheap first-pass filters can handle safely, the defender usually needs a deeper mitigation path. This is where scrubbing enters.
A scrubbing system sits in the high-volume path and tries to answer a harder question than the stateless edge can answer: which flows are likely legitimate enough to keep, and how can they be forwarded to the customer without letting the flood follow them?
There are two broad deployment models.
Always-on mitigation keeps customer traffic behind the provider edge all the time. Every request already terminates or is proxied through the mitigation network, so the defence path is already in place when the attack starts.
On-demand mitigation leaves the service on a more direct path during quiet periods and diverts it only during an attack. Diversion can happen through BGP advertisement changes, GRE or Geneve tunnel steering, or provider-side control-plane actions that move the target prefix into a scrubbed path.
The basic flow looks like this:
botnet / reflectors
-> nearest anycast edge
-> mitigation classifier
-> drop bad traffic
-> encapsulate clean traffic
-> GRE or Geneve tunnel to customer edge or private interconnect
-> origin proxy or load balancerThe classifier is not one algorithm. Real systems combine several signals:
- protocol and port expectations for that customer
- packet size distributions and flag ratios
- spoofing confidence and reflection signatures
- sudden ASN or prefix surges
- historic per-customer baselines
- challenge results or failed handshakes
- cacheability and HTTP behaviour at L7 when decryption is in path
This is also where blunt routing tools still matter. Remote triggered black hole routing, usually shortened to RTBH, is intentionally brutal: discard traffic for a target prefix so the rest of the network survives. It protects the surrounding infrastructure by sacrificing reachability for the attacked address. FlowSpec is more surgical. It distributes match-and-action rules such as dropping a protocol, prefix, or port pattern across participating routers. Both are useful when the alternative is broader collateral damage.
Operationally, large providers often expose this control with communities or automation hooks that look conceptually like this:
64500:120 steer prefix to Frankfurt scrubber
64500:130 steer prefix to Amsterdam scrubber
65535:666 blackhole /32 or /128 at edgeThe numeric values vary by operator. The pattern does not. DDoS mitigation is deeply intertwined with routing control.
Scrubbing is not free. The deeper the inspection, the more latency, state, and false-positive risk the defender introduces. Encrypted traffic is especially awkward. A provider that does not terminate TLS sees limited L7 information. A provider that does terminate TLS gains visibility, but must now own certificate handling, privacy boundaries, and a far more sensitive operational role. That tradeoff is one reason some customers put only selected services behind full proxy mitigation while keeping others behind more limited network-layer protection.
The goal is not to label every packet with perfect philosophical accuracy. The goal is to keep enough good traffic moving that the service remains useful.
Application-Layer Floods Are Fights Over Work, Not Over Wire Speed
The hardest DDoS attacks to explain to non-specialists are usually the ones with unimpressive bandwidth graphs.
A service can be taken down by traffic that looks almost polite on the wire.
Suppose an attacker sends 40,000 requests per second to a static image path that is already cached on the edge. That may be cheap. Now suppose the attacker sends 40,000 requests per second to /search, each request carrying parameters that defeat the cache, trigger authentication, hit a personalisation service, fan out to a ranking backend, and allocate work in two internal queues. The bandwidth might still be modest. The backend cost is not.
This is why application-layer mitigation starts with cost accounting.
A useful mental model is to price routes in work units:
GET /landing cost 1
GET /catalog cost 2
POST /login cost 4
POST /search cost 20
POST /render-pdf cost 80If you only count raw request rate, you hide the real overload path.
The mitigation tools at this layer are different from volumetric filtering tools:
- edge caching and origin shielding for cacheable paths
- request coalescing so one cache miss does not trigger many identical backend fetches
- per-route rate limits and concurrency caps
- challenge pages, JavaScript challenges, proof-of-work, or token issuance for suspicious anonymous traffic
- prioritisation of authenticated or high-value sessions over anonymous bulk traffic
- queue limits with fast rejection instead of slow collapse
- degraded response modes such as stale reads, reduced personalisation, or temporarily disabled expensive features
HTTP/2 and HTTP/3 complicate this because one connection can multiplex many requests. Connection counts alone are therefore a poor signal. Modern floods often look like well-behaved browsers or headless Chromium fleets behind residential proxies. The operator may need to score behaviour at the session, identity, cookie, and route level, not just at the IP level.
The public reporting around the 2023 HTTP/2 Rapid Reset issue made this visible. The remarkable part was not only the enormous reported request rates. It was how cheaply an attacker could trigger work in a protocol feature that was otherwise legitimate. That is the recurring lesson at L7: if the protocol lets a client ask for expensive work quickly, the attacker will turn that into an asymmetry.
A practical response plan often looks less heroic than people expect:
- cache everything that can be cached
- force suspicious anonymous traffic through a challenge or token path
- put tight per-route budgets on the expensive endpoints
- preserve checkout, login, and core API writes
- shed optional features such as full-text suggestions, rich personalisation, previews, or export jobs
Notice the theme. The defender is not trying to prove human innocence with perfect confidence. The defender is trying to spend scarce backend work on the flows that matter most.
That is why DDoS mitigation and rate limiting overlap heavily at the application edge. When the fight reaches L7, admission control becomes part of the defence surface.
Origin Protection Fails If The Origin Can Still Be Reached Directly
A surprising number of DDoS defences fail because the public edge is protected but the origin remains reachable by some simpler path.
If an attacker can discover the real origin IP and send traffic there directly, they can bypass:
- CDN caching
- edge anycast absorption
- L7 challenge systems
- WAF and bot controls at the public proxy
- customer-specific scrubbing policy attached to the edge hostname
Origin exposure happens in mundane ways.
A forgotten DNS record points directly at the backend. A mail service or staging host shares the same address range. The application makes outbound calls that reveal the source address. A certificate or support header leaks infrastructure naming. A monitoring endpoint is left on a public interface because it was convenient during setup. None of these mistakes sounds dramatic. Under attack, they are fatal shortcuts.
The fix is architectural, not rhetorical. The origin should accept traffic only from the trusted edge or trusted tunnel path. That can mean provider private connectivity, mTLS between edge and origin, strict IP allowlists, or all three.
A minimal allowlist posture often looks like this:
allow 203.0.113.0/24;
allow 2001:db8:100::/48;
deny all;The addresses above are documentation ranges, but the idea is real. If a request does not arrive from the provider edge, the origin should not serve it.
For private deployments, the cleaner model is even stronger:
- the public hostname resolves only to the edge network
- the origin lives on private address space or a non-advertised public path
- the origin requires a client certificate or signed edge identity
- direct internet ingress to the origin is impossible, not merely discouraged
Caching and shielding also matter here. If the edge can answer most safe reads from cache and only a small clean subset reaches the origin, the origin stays stable. If every edge miss goes straight to a globally reachable backend, a smaller second-stage flood can still finish the job.
Testing for bypass is part of the defence. Good teams periodically ask boring but essential questions:
- can I reach the origin IP directly from the public internet?
- does the origin respond to the public hostname without the edge in front?
- are there stale DNS records that point around the edge?
- do staging, admin, API, and static assets all share the same protection posture?
- can an attacker force an uncached path that skips edge controls?
The answers are rarely exciting, but they determine whether the expensive front-door mitigation actually protects the thing you care about.
Mitigation Is An Operations Discipline, Not A Magic Appliance
DDoS response works best when the technical controls and the operating model fit each other.
The control surface is broad:
- routing communities or API calls to steer traffic into scrubbing
- source-of-truth inventory for which hostnames and prefixes map to which services
- emergency cache rules and stale-content settings
- application feature flags for shedding expensive functionality
- contact paths with transit providers, cloud providers, and mitigation vendors
- dashboards that show bps, pps, connection rates, backend cost, and error budgets in one place
The monitoring has to reflect the attack families, not just the marketing story.
A useful live incident view usually includes at least:
- ingress Gbps and Mpps by PoP
- top source ASNs and prefixes by share
- top protocols and port patterns
- SYN backlog, conntrack occupancy, and handshake failure rate
- TLS CPU, handshake latency, and connection reuse ratio
- cache hit ratio, origin request rate, and shield hit ratio
- per-route request rates for expensive endpoints
- challenge success rate and challenge abandonment rate
- origin p95 and p99 latency, 5xx rate, and queue depth
A good incident timeline ends up reading like engineering, not like mysticism:
09:14 UTC ingress climbs to 320 Gbps and 41 Mpps
09:15 UTC UDP/53 reflection dominates, spoof confidence high
09:16 UTC affected prefixes steered to Amsterdam and Frankfurt scrubbing
09:17 UTC clean tunnel stabilises at 6.4 Gbps, origin loss stops
09:19 UTC secondary HTTP flood starts on /search and /login
09:20 UTC anonymous /search moved to challenge path, login concurrency capped
09:23 UTC p95 origin latency returns below 180 msThat level of clarity does not appear spontaneously during an incident. It comes from drills, known runbooks, preapproved mitigation levers, and a shared language between network, platform, and application teams.
False positives are part of the discipline. A defensive rule that blocks real users can become a self-inflicted denial of service. This is especially dangerous at L7, where behavioural scoring and challenges are inevitably imperfect. Mature operators therefore prefer staged mitigations where possible:
- measure and sample first
- apply narrow rules to one hostname, prefix, path, or geography slice
- watch legitimate error rates and challenge solve rates
- widen only when the evidence is clear
- keep rollback paths faster than the rule deployment path
This is also where provider choice matters. A mitigation network with excellent raw capacity but poor telemetry or slow policy rollout can still leave the customer blind. Capacity buys time. Control planes turn time into a useful response.
The Real Goal Is Graceful Degradation And Better Economics
The public story about DDoS defence often sounds absolute: block the attack, keep the site online, problem solved.
Real operations are usually more measured. The goal is to keep important user journeys alive, contain collateral damage, and avoid spending more on mitigation than the attacker spends on abuse.
That economic part matters. Attackers look for asymmetry. If a forged UDP packet costs them almost nothing but forces the defender to burn CPU and analyst time, they are winning. If a browser-like request causes a cache miss, a search fan-out, and a €0.02 third-party verification call, then even a moderate request rate can become a cost attack as well as an availability attack.
Good mitigation restores asymmetry in the defender's favour:
- anycast spreads the flood across cheaper edge capacity
- stateless filters drop junk before expensive inspection
- cookies and Retry avoid premature per-client state
- scrubbing tunnels only the traffic worth forwarding
- caches answer cheap content without waking the origin
- route budgets and concurrency caps protect the expensive paths
- feature shedding preserves core workflows while optional work is paused
This is why graceful degradation is a serious engineering goal, not an apology. During a sustained attack, it may be perfectly rational to:
- serve stale product pages from cache
- disable anonymous search suggestions
- postpone report exports and bulk jobs
- prioritise authenticated customers over anonymous traffic
- narrow API quotas to essential methods only
- present challenge flows to suspicious segments
That posture is not surrender. It is the service choosing what it will protect first.
If there is one idea worth keeping, it is this: DDoS mitigation works by moving the trust boundary outward and the expensive work inward. The edge absorbs and validates. The scrubber classifies and tunnels. The origin accepts only what the outer layers have earned the right to send. The application spends its scarce work budget on the flows that matter most.
That is not one feature. It is a layered capacity design for surviving hostile traffic on the real internet.