{"id":12160,"library":"toxiproxy-node-client","title":"Toxiproxy Node Client","description":"The `toxiproxy-node-client` is a JavaScript and TypeScript client library for interacting with Toxiproxy, a powerful tool developed by Shopify for simulating real-world network conditions such as high latency, bandwidth limitations, and connection drops. This library, currently at stable version 4.0.0, provides a programmatic interface to configure Toxiproxy proxies and add various network 'toxics' to test the resilience and error handling of applications. While there isn't a fixed public release cadence, major versions like v4 typically introduce significant API updates or broader compatibility. Its key differentiator is being the primary Node.js interface for Toxiproxy, enabling developers to integrate network chaos engineering directly into their Node.js testing and development workflows without manual intervention. It ships with full TypeScript type definitions, making it suitable for both JavaScript and TypeScript projects.","status":"active","version":"4.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/ihsw/toxiproxy-node-client","tags":["javascript","typescript"],"install":[{"cmd":"npm install toxiproxy-node-client","lang":"bash","label":"npm"},{"cmd":"yarn add toxiproxy-node-client","lang":"bash","label":"yarn"},{"cmd":"pnpm add toxiproxy-node-client","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The primary `Toxiproxy` class is a named export for ESM/TypeScript. For CommonJS, use `const client = require('toxiproxy-node-client'); new client.Toxiproxy(...)`.","wrong":"import Toxiproxy from 'toxiproxy-node-client';","symbol":"Toxiproxy","correct":"import { Toxiproxy } from 'toxiproxy-node-client';"},{"note":"Type definitions like `ICreateProxyBody` are available via named imports. They are TypeScript-specific and do not exist at runtime in JavaScript.","wrong":"const ICreateProxyBody = require('toxiproxy-node-client').ICreateProxyBody;","symbol":"ICreateProxyBody","correct":"import type { ICreateProxyBody } from 'toxiproxy-node-client';"},{"note":"Specific toxic attribute types, such as `Bandwidth` for bandwidth toxics, are exported as TypeScript types for strong typing during configuration.","symbol":"Bandwidth","correct":"import type { Bandwidth } from 'toxiproxy-node-client';"}],"quickstart":{"code":"import { Toxiproxy, ICreateProxyBody, ICreateToxicBody, Bandwidth } from \"toxiproxy-node-client\";\n\nasync function run() {\n    const toxiproxy = new Toxiproxy(\"http://localhost:8474\");\n    const proxyBody: ICreateProxyBody = {\n      listen: \"localhost:0\", // Listen on an ephemeral port\n      name: \"redis-proxy\", // Give it a unique name\n      upstream: \"redis:6379\" // Target the actual Redis instance\n    };\n\n    try {\n        console.log(`Creating proxy for upstream: ${proxyBody.upstream}`);\n        const proxy = await toxiproxy.createProxy(proxyBody);\n        console.log(`Proxy '${proxy.name}' created, listening on ${proxy.listen}`);\n\n        const toxicBody: ICreateToxicBody<Bandwidth> = {\n          attributes: { rate: 1000 }, // 1000 KB/s\n          type: \"bandwidth\",\n          name: \"limit-bandwidth\"\n        };\n\n        console.log(`Adding bandwidth toxic (${toxicBody.attributes.rate} KB/s) to proxy '${proxy.name}'`);\n        const toxic = await proxy.addToxic(toxicBody);\n        console.log(`Toxic '${toxic.name}' of type '${toxic.type}' added.`);\n\n        // In a real scenario, you would now run your tests against proxy.listen\n        // e.g., connect your Redis client to proxy.listen, not redis:6379 directly.\n\n        // Clean up: remove the toxic and then the proxy\n        console.log(`Removing toxic '${toxic.name}'...`);\n        await proxy.deleteToxic(toxic.name);\n        console.log(`Toxic removed. Deleting proxy '${proxy.name}'...`);\n        await toxiproxy.deleteProxy(proxy.name);\n        console.log(\"Proxy deleted successfully.\");\n    } catch (error: any) {\n        console.error(\"Error interacting with Toxiproxy:\", error.message);\n        console.error(\"Ensure Toxiproxy server is running on http://localhost:8474\");\n        console.error(\"You can run it via Docker: `docker run --rm -p 8474:8474 ghcr.io/shopify/toxiproxy:latest`\");\n    }\n}\n\nrun();","lang":"typescript","description":"This quickstart demonstrates how to create a Toxiproxy client, set up a proxy for a Redis instance, add a bandwidth-limiting toxic, and then clean up both the toxic and the proxy. It includes error handling and guidance for ensuring the Toxiproxy server is running."},"warnings":[{"fix":"For ESM/TypeScript, use `import { SymbolName } from 'toxiproxy-node-client';`. For CommonJS, use `const client = require('toxiproxy-node-client'); const SymbolName = client.SymbolName;`","message":"Module Import Syntax: While v4.x supports both CommonJS `require` and ES Module `import` syntax, ensure you use named imports for ESM and TypeScript (e.g., `import { Toxiproxy } from 'toxiproxy-node-client'`). Attempting a default import will result in errors. Earlier versions (e.g., v3.x) might have had different import patterns or primary support for CommonJS.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Before running your Node.js application, start the Toxiproxy server. The easiest way is using Docker: `docker run --rm -p 8474:8474 ghcr.io/shopify/toxiproxy:latest`.","message":"`toxiproxy-node-client` is a client library and requires a running Toxiproxy server instance to function. All operations will fail with connection refused errors (e.g., `ECONNREFUSED`) if the server (typically listening on `http://localhost:8474`) is not accessible.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure all proxy names are unique. Consider appending a timestamp or a UUID to proxy names, especially in automated testing environments.","message":"Each proxy created via the client must have a globally unique `name` within the Toxiproxy server instance. Attempting to create a proxy with a name that already exists on the server will result in an error. This is crucial in test suites where proxies might be created and torn down frequently.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Provide unique names for each toxic you add to a proxy. If applying multiple toxics of the same type, differentiate their names.","message":"Similarly, each toxic added to a specific proxy must have a unique `name` within that proxy. Using duplicate toxic names for the same proxy will cause errors from the Toxiproxy server.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Start the Toxiproxy server, for example, using Docker: `docker run --rm -p 8474:8474 ghcr.io/shopify/toxiproxy:latest`. Verify that the `Toxiproxy` client is configured to connect to the correct endpoint.","cause":"The Toxiproxy server is not running or is inaccessible at the specified address and port.","error":"connect ECONNREFUSED 127.0.0.1:8474"},{"fix":"Use a unique name for each proxy. In testing scenarios, consider programmatically generating unique names (e.g., `my-proxy-${Date.now()}`).","cause":"You attempted to create a proxy with a name that is already in use by another proxy on the Toxiproxy server.","error":"Error: Proxy 'my-proxy-name' already exists"},{"fix":"Explicitly specify the toxic type, for example, `const toxicBody: ICreateToxicBody<Bandwidth> = { ... };`. Ensure you have imported the specific toxic type (e.g., `Bandwidth`) if needed.","cause":"When using TypeScript, the generic type `T` for `ICreateToxicBody` (representing the specific toxic's attributes) has not been explicitly provided or inferred correctly.","error":"Argument of type '{ attributes: { rate: number; }; type: \"bandwidth\"; }' is not assignable to parameter of type 'ICreateToxicBody<T>'."}],"ecosystem":"npm"}