<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: zerodawnstress</title>
    <description>The latest articles on DEV Community by zerodawnstress (@zerodawnipstress).</description>
    <link>https://dev.to/zerodawnipstress</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4079287%2F2829d506-d5dc-4ec0-943a-2b31ed286943.jpg</url>
      <title>DEV Community: zerodawnstress</title>
      <link>https://dev.to/zerodawnipstress</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zerodawnipstress"/>
    <language>en</language>
    <item>
      <title>L4 vs L7 Stress Testing: What Actually Breaks First</title>
      <dc:creator>zerodawnstress</dc:creator>
      <pubDate>Sat, 15 Aug 2026 17:17:24 +0000</pubDate>
      <link>https://dev.to/zerodawnipstress/l4-vs-l7-stress-testing-what-actually-breaks-first-3k7p</link>
      <guid>https://dev.to/zerodawnipstress/l4-vs-l7-stress-testing-what-actually-breaks-first-3k7p</guid>
      <description>&lt;p&gt;Stress testing a network service is not one discipline — it's two. Layer 4 and Layer 7 tests break things in fundamentally different ways, and confusing them is the single most common mistake I see in infrastructure testing reports.&lt;/p&gt;

&lt;p&gt;Here's the mental model that finally made it click for me.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Two Questions
&lt;/h2&gt;

&lt;p&gt;Every stress test answers one of two questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;L4:&lt;/strong&gt; "Can the pipes and the connection machinery survive the volume?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L7:&lt;/strong&gt; "Can the application actually do its job under load?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L4 attacks the delivery system — routers, firewalls, TCP stacks, conntrack tables. L7 attacks the business logic — web workers, TLS handshakes, database pools, render pipelines.&lt;/p&gt;

&lt;p&gt;An analogy: L4 is blocking every road leading to a building. L7 is sending a thousand people to the reception desk to ask questions. Both overwhelm. They are not interchangeable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What L4 Actually Consumes
&lt;/h2&gt;

&lt;p&gt;Three distinct resources, and people constantly mix them up:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Bandwidth (Gbps).&lt;/strong&gt; Raw bits per second. Determined by uplink capacity and any scrubbing capacity upstream.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Packets per second (PPS).&lt;/strong&gt; This is where intuition fails. 1 Gbps of 64-byte packets is roughly 1.95 million PPS. The same 1 Gbps of 1400-byte packets is about 89,000 PPS — a 23x difference. Network gear processes &lt;em&gt;packets&lt;/em&gt;, not bytes. A mid-range firewall that happily forwards 9 Gbps of large packets can fall over at 3 Gbps of small ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Connection state (conntrack / file descriptors).&lt;/strong&gt; SYN floods and full TCP connection floods target the &lt;em&gt;tables&lt;/em&gt;, not the bandwidth. A device can be at 4% CPU with an empty uplink and still be dying because its session table is full.&lt;/p&gt;

&lt;p&gt;Quick conversion reference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PPS ≈ Gbps × 125,000,000 / avg_packet_size_bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What L7 Actually Consumes
&lt;/h2&gt;

&lt;p&gt;Application-layer pressure targets computational cost:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Web workers / thread pools&lt;/strong&gt; — request concurrency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TLS handshakes&lt;/strong&gt; — asymmetric crypto is expensive on the server side, cheap on the client side (this asymmetry is the whole point of TLS-based tests)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database connections&lt;/strong&gt; — any endpoint that touches storage multiplies cost&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic rendering&lt;/strong&gt; — endpoints that build pages per-request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The metric that matters here is &lt;strong&gt;RPS&lt;/strong&gt; (requests per second) combined with response-time degradation. Raw RPS means nothing without a latency baseline: 5,000 RPS at 40ms p95 is fine; 5,000 RPS at 4,000ms p95 means you already lost.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottleneck Location Table
&lt;/h2&gt;

&lt;p&gt;This is the cheat sheet I keep coming back to:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom under load&lt;/th&gt;
&lt;th&gt;Bottleneck&lt;/th&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Bandwidth saturated, service responsive&lt;/td&gt;
&lt;td&gt;Uplink / scrubbing&lt;/td&gt;
&lt;td&gt;L4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Low bandwidth, but device CPU spiking&lt;/td&gt;
&lt;td&gt;Firewall PPS limit&lt;/td&gt;
&lt;td&gt;L4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SYN_RECV queue climbing&lt;/td&gt;
&lt;td&gt;TCP backlog&lt;/td&gt;
&lt;td&gt;L4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Conntrack table full, drops everywhere&lt;/td&gt;
&lt;td&gt;Connection state table&lt;/td&gt;
&lt;td&gt;L4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Response times climbing, 5xx rising&lt;/td&gt;
&lt;td&gt;App workers / DB pool&lt;/td&gt;
&lt;td&gt;L7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TLS handshake failures rising&lt;/td&gt;
&lt;td&gt;Crypto offload exhausted&lt;/td&gt;
&lt;td&gt;L7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache hit ratio collapses&lt;/td&gt;
&lt;td&gt;Origin protection gap&lt;/td&gt;
&lt;td&gt;L7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The Three Mistakes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Testing only one layer.&lt;/strong&gt; Defenses degrade differently per layer. A stack that survives 10 Gbps of UDP can die to 20k RPS of well-formed HTTPS requests. Test both, then test them mixed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reading peaks, ignoring sustained load.&lt;/strong&gt; Surviving a 30-second spike is not the same as surviving 40 minutes. Thermal throttling, garbage collection pauses, and connection accumulation only show up under sustained pressure. Always record both peak and 10-minute sustained numbers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No baseline.&lt;/strong&gt; If you don't know your p95 latency before the test, your test produced a number, not an answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  A sane test sequence
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Baseline: normal-traffic latency percentiles for 10 minutes&lt;/li&gt;
&lt;li&gt;Single-method L4 runs — find each threshold separately&lt;/li&gt;
&lt;li&gt;Single-method L7 runs — same&lt;/li&gt;
&lt;li&gt;Mixed runs at ratios approximating your threat model&lt;/li&gt;
&lt;li&gt;Record: threshold (where degradation starts), cliff (where it collapses), recovery time after stopping&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The threshold is more operationally useful than the cliff. Alerts should fire near thresholds; the cliff is where incident response has already failed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;Stop asking "how much traffic can we survive" and start asking "which resource exhausts first, and how do we see it before users do." Layer 4 and Layer 7 give you different answers to that question — and you need both.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>security</category>
      <category>testing</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
