Frontend Labs
⋯

8. Simulating Network Conditions

Load (concurrency/throughput) is only half the story — real users are on imperfect networks. Simulating latency, jitter, and packet loss surfaces bugs that a pristine localhost/datacenter test never will (timeout tuning, retry storms, TCP behavior under loss).

8.1 tc + netem (Linux) — kernel-level network emulation

# add 100ms latency +/- 20ms jitter (normal distribution) on eth0 egress
sudo tc qdisc add dev eth0 root netem delay 100ms 20ms distribution normal

# add 2% packet loss on top
sudo tc qdisc change dev eth0 root netem delay 100ms 20ms loss 2%

# simulate a constrained mobile link: 100ms delay, 1% loss, 1mbit cap
sudo tc qdisc add dev eth0 root handle 1: netem delay 100ms loss 1%
sudo tc qdisc add dev eth0 parent 1: handle 10: tbf rate 1mbit burst 32kbit latency 400ms

# remove all shaping when done
sudo tc qdisc del dev eth0 root

For containerized targets, apply netem inside the container's network namespace (or on a dedicated bridge) so you don't degrade the host's other traffic:

# apply to a specific docker container's interface
CID=$(docker inspect -f '{{.State.Pid}}' my_service_container)
sudo nsenter -t $CID -n tc qdisc add dev eth0 root netem delay 150ms 30ms loss 1%

Common real-world profiles to script as reusable presets:

Profile Command suffix
Good WiFi delay 5ms 2ms
4G delay 50ms 20ms loss 0.5%
3G delay 150ms 50ms loss 2% rate 750kbit
Satellite delay 600ms 50ms loss 1%
Congested intercontinental link delay 200ms 40ms loss 3% rate 5mbit

8.2 Toxiproxy — application-level fault injection proxy

Unlike tc (kernel-wide, needs root, per-interface), Toxiproxy sits as a TCP proxy in front of a specific dependency (DB, downstream API) and lets you inject/ remove faults at runtime via HTTP API — ideal for automated test suites.

docker run -d --name toxiproxy -p 8474:8474 -p 5433:5433 ghcr.io/shopify/toxiproxy

# create a proxy: app connects to localhost:5433 instead of the real DB directly
curl -X POST http://localhost:8474/proxies \
  -d '{"name":"postgres","listen":"0.0.0.0:5433","upstream":"postgres_real:5432"}'

# inject 200ms latency with 50ms jitter on all upstream traffic
curl -X POST http://localhost:8474/proxies/postgres/toxics \
  -d '{"type":"latency","attributes":{"latency":200,"jitter":50}}'

# simulate the DB link going completely dark (timeout testing)
curl -X POST http://localhost:8474/proxies/postgres/toxics \
  -d '{"type":"timeout","attributes":{"timeout":0}}'

Run your standard load test (k6/Locust/wrk) against the app while Toxiproxy injects DB latency — this directly validates the timeout/circuit-breaker/bulkhead behavior described in §5.3, under real concurrent load rather than a single manual request.

8.3 Comcast (Go) — simpler netem wrapper, cross-platform-ish CLI

go install github.com/tylertreat/comcast@latest
comcast --latency=150 --packet-loss=5% --target-bw=1000 --device=eth0
comcast --stop   # remove all rules

Generated from real-life-scale-guide.md · 8 Oct 2026 16:36