Pick a depth. Each prompt opens in your AI pre-loaded with the lesson. Click a row to preview the prompt.
Bandwidth is the number everyone quotes because it is printed on the network card, and packets per second is the number that actually stops you. The reason is arithmetic: the network stack pays a fixed cost per packet — an interrupt or a poll, a descriptor, a socket buffer walk, a protocol lookup — and that cost barely changes whether the packet carries 60 bytes or 1,460. So your card's rated speed is only reachable at full-size frames, and API traffic is nowhere near full-size frames. The failure mode is genuinely confusing the first time you meet it: the bandwidth graph reads 6 Gbps on a 25 Gbps card, every dashboard looks healthy, and the box is quietly dropping packets because one core sits pinned at 100 percent in softirq while thirty-one others idle. Worse, the packet count per request is not fixed — it depends on whether the client reused the connection. A cold TLS connection spends roughly fifteen packets to deliver one response; the same request on a warm keep-alive connection spends four. That is a factor of nearly four in your packet budget, decided entirely by client behaviour you do not control, and it is why connection reuse is a capacity decision rather than a nicety.
Break one request into packets both ways — cold and warm — then multiply. The diagram counts the packets; the script turns them into a packets-per-second figure and a gigabits figure, and then compares the two against the same card.
# packets.py — a million requests a second, in packets and in bits
RPS = 1_000_000
REQ_BYTES = 800 # method, path, headers, cookies. Measure yours.
RESP_BYTES = 2_048 # JSON body plus response headers
MSS = 1_460 # 1500-byte MTU minus 20 IP minus 20 TCP
def packets(nbytes):
return max(1, -(-nbytes // MSS)) # ceiling division
warm = packets(REQ_BYTES) + packets(RESP_BYTES) + 1 # request + response + ACK
cold = warm + 3 + 5 + 3 # TCP handshake, TLS, teardown
for name, ppr in (("keep-alive", warm), ("cold connection", cold)):
print(f"{name:>16}: {ppr:>2} packets/req -> {RPS * ppr / 1e6:5.1f} Mpps")
# keep-alive: 4 packets/req -> 4.0 Mpps
# cold connection: 15 packets/req -> 15.0 Mpps
bits = RPS * (REQ_BYTES + RESP_BYTES) * 8
print(f"wire rate: {bits / 1e9:.1f} Gbps")
# wire rate: 22.8 Gbps
avg_frame = (REQ_BYTES + RESP_BYTES) / warm
print(f"average frame: {avg_frame:.0f} bytes — the MTU is 1500, you are nowhere near it")
# average frame: 712 bytes
# What that means against a 25 Gbps card:
NIC_GBPS = 25
print(f"pps available at this frame size: "
f"{NIC_GBPS * 1e9 / (avg_frame * 8) / 1e6:.1f} Mpps")
# pps available at this frame size: 4.4 MppsRESP_BYTES to 200, the size of a small acknowledgement JSON, and re-run. Bandwidth collapses to about 8 Gbps but packets per second barely move. That gap is the entire lesson: request count sets packets, payload size sets bits, and they fail independently.sar -n DEV 1 5 on a box under real load and divide rxpck/s by the rps your metrics report for the same window. If the answer is above 6, connections are not being reused; confirm it by watching nstat -az | grep -i passiveopens over the same interval and comparing that rate against your rps.mpstat -P ALL 1 5 and read the %soft column. If one core is above 60 percent while the rest idle, the card is steering everything to a single receive queue. Check ethtool -l eth0 for how many combined queues exist versus how many are currently enabled.curl -s -o /dev/null -w '%{size_request} %{size_download}' https://your-endpoint, then put both numbers into the script. Cookie-heavy apps routinely send 3 KB requests, which quietly doubles the request-side packet count.ethtool -S eth0 | grep -i drop twice, ten seconds apart, on a loaded box. Any counter that moved is a request you were paid to serve and did not.