Unlike a breach, a denial-of-service (DoS) attack does not take anything from the target; it takes the target away from its users. That failure, provoked on purpose and measured, is what every DDoS test is designed to produce. The attack aims to make a service unreachable to legitimate users by exhausting a finite resource: bandwidth, CPU, memory, connection state, or an application worker pool.
A classic DoS originates from a single source, so filtering one address usually stops it. A distributed denial-of-service (DDoS) spreads the same load across thousands of hosts, which is why source-based blocking alone fails and mitigation has to key on behavior, protocol conformance, and rate rather than origin.
Three resources, and one that needs no volume
Every DoS runs something out. Which thing it runs out sorts the attack into a family.
The pipe. Fill the link or the upstream capacity in front of the service, and nothing behind it matters. This is the volumetric attack, sized in bits per second.
The state. Fill a table that some device keeps per connection or per flow: a firewall's session table, a load balancer's connection slots, a server's half-open queue. The link can sit mostly empty while the box in the middle stops accepting new work. That is the protocol attack, sized in packets per second.
The work. Send requests that are each legitimate and each expensive, so the application spends its CPU, threads and database connections on them. That is the application-layer attack, sized in requests per second.
The fourth case breaks the pattern. Some denials need no flood at all, because a single input triggers far more work than it should. A crafted set of form fields that all hash to the same bucket, the hash collision DoS disclosed against most web languages in 2011, could keep a CPU core busy for a long time per request. A regular expression with catastrophic backtracking does the same. These are true DoS attacks from one source, and adding sources barely changes them, which is why they do not depend on the D.
The denial is in the user's experience, not the server's
A service can be denied while every host in it reports healthy. The load balancer passes health checks, the processes are running, the CPU graph is high but not pinned, and the checkout page takes forty seconds. To the customer that is an outage. To the monitoring it may be nothing.
The reverse also happens. A host can be on fire while users notice nothing, because the cache or a second region absorbs the load. So the useful definition of "denied" is written in user terms, before any traffic is sent: the share of real transactions that succeed, and the latency a user tolerates for each.
Intent does not change the failure either. A launch-day traffic spike, a client release with an aggressive retry loop, or a dependency timing out and multiplying its callers can each exhaust the same resource an attacker would. The defense and the test treat them the same way, because the user cannot tell them apart.
What a DDoS test measures about it
DoS is the outcome; the vector is how you reach it. A test does not just confirm that a flood causes an outage, it identifies which resource fails first and at what load, so the fix targets the real bottleneck rather than the symptom. Whether the accept queue, the WAF, the origin CPU, or an upstream link gives way decides what you buy or tune next.
Three readings matter more than the peak rate:
- The degradation point. The load at which success rate or latency first leaves its agreed band, which usually arrives well before anything falls over.
- Detection against degradation. Whether mitigation engages before that point, or after users have already noticed.
- Recovery. Whether the service comes back on its own when the traffic stops. Exhausted state, stuck queues and scaled-out capacity that never scales back in can each hold a denial in place after the attack has ended.
Turning those three readings into a decision about where the next round of hardening goes is the job of DDoS resilience testing.