What each tool is
Toxiproxy is a TCP proxy that sits between your application and a real or test service. It intercepts network connections and injects faults: latency, bandwidth limits, connection resets, timeouts. It's language-agnostic and requires running a separate process (or Docker container).
slowdep is an npm package that wraps async JavaScript/TypeScript functions directly. No proxy, no Docker, no separate process. You import it, wrap a function, and it adds lognormal latency. It runs entirely in your Node.js test process.
Comparison table
| feature | toxiproxy | slowdep |
|---|---|---|
| scope | network layer — all TCP traffic | function level — per-function control |
| setup complexity | high — separate binary or Docker service | low — npm install, one import |
| language support | any — language-agnostic | Node.js / TypeScript only |
| CI overhead | high — needs Docker or binary in CI | zero — pure npm dependency |
| Docker required | recommended | never |
| production-safe | no — only for test environments | yes — wrapping is safe, just slow |
| test determinism | configurable latency, but fixed | probabilistic (lognormal); seed Math.random for determinism |
| granularity | per-connection — affects all calls to a host:port | per-function — different latency per method |
| latency distribution | fixed, jitter, or random within range | lognormal — matches real production distributions |
| streaming support | can simulate slow streams byte-by-byte | delays the function call start, not stream chunks |
When to use Toxiproxy
Toxiproxy excels when you need to test network-level behavior that a function wrapper can't model:
When to use slowdep
slowdep is the right choice when you want realistic latency with minimal infrastructure:
When to use both
Toxiproxy and slowdep complement each other in a layered testing strategy. Use them at different levels of the test pyramid for maximum coverage.
// Example: Docker Compose integration test // Toxiproxy ? real Postgres (network-level faults) // slowdep ? S3 mock (function-level latency, no network) // docker-compose.yml excerpt: // toxiproxy: { image: shopify/toxiproxy, ports: [8474, 5433] } // postgres: { image: postgres:16, ports: [5432] } import { withLatency } from 'slowdep'; // Postgres: via Toxiproxy (real TCP connection, network faults) const db = new Pool({ host: 'localhost', port: 5433 }); // Toxiproxy port // S3: mocked function with slowdep (no real S3 in CI) const s3 = withLatency(mockS3.getObject, 's3'); // p50:30ms, p99:500ms // Together: realistic latency at every layer, realistic distribution
Toxiproxy tests your code's resilience to network faults. slowdep tests your code's resilience to dependency latency. Both gaps exist. Both need testing.