@priyabrat/chaos-route
v0.0.4
Published
Test your application by injecting intentional error to your route
Maintainers
Readme
Chaos Route
Intentionally break your Express.js API routes to test how your application handles failures.
Chaos Route is an Express middleware package for controlled fault injection during development and testing.
It lets you configure failures for specific routes without modifying your controllers or frontend code.
For example, you can make /api/login timeout, return a 500 error, or introduce artificial latency simply by changing chaos.config.json.
Table of Contents
Why Chaos Route?
Applications usually work perfectly during development.
But what happens when:
- Login takes too long?
- An API suddenly returns
500? - A request is delayed by several seconds?
- Your frontend receives an unexpected backend failure?
- Your loading state never finishes?
- Your error handling isn't actually working?
Chaos Route lets you intentionally create these situations so you can test how your application behaves when things go wrong.
Installation
npm install @priyabrat/chaos-route;OR
npm install @priyabrat/chaos-route -D;Quick Start
1. Add Chaos Route to your Express application
import express from "express";
import { chaos } from "@priyabrat/chaos-route";
const app = express();
app.use(chaos());
app.post("/api/login", loginController);
app.listen(5000, () => {
console.log("Server running on port 5000");
});Place chaos() before the routes you want to test.
2. Create chaos.config.json
Create this file in the root of your application:
my-express-app/
├── src/
├── package.json
├── chaos.config.json
└── ...Example:
{
"routes": {
"/api/login": {
"failure": {
"type": "http_error",
"status": 500,
"message": "Login service failed"
}
}
}
}Now every request to:
POST /api/loginwill receive the configured failure instead of reaching your login controller.
How It Works
Chaos Route runs as normal Express middleware.
Client
│
│ POST /api/login
▼
Express
│
▼
Chaos Route
│
├── No configuration ──────→ next()
│
├── Latency ────────────────→ wait → next()
│
└── HTTP Error ─────────────→ return errorYour existing controllers don't need to know that Chaos Route is being used.
For example:
app.use(chaos());
app.post("/api/login", loginController);With no failure configured:
Request
↓
Chaos Route
↓
loginController
↓
ResponseWith an HTTP error configured:
Request
↓
Chaos Route
↓
500 ErrorThe loginController is never executed.
Configuration
The configuration file(chaos.config.json) uses this structure:
{
"routes": {
"/your-route": {
"failure": {
"type": "...",
"status": "code",
"message": "..."
}
}
}
}Each route can have its own failure configuration.
HTTP Error
Return a controlled HTTP error from a route.
{
"routes": {
"/api/login": {
"failure": {
"type": "http_error",
"status": 500,
"message": "Login service unavailable"
}
}
}
}A request to /api/login will receive:
{
"error": "Login service unavailable",
"chaos": true
}Options
| Option | Type | Default | Description |
| --------- | -------------- | --------------- | ---------------- |
| type | "http_error" | — | Failure type |
| status | number | 500 | HTTP status code |
| message | string | "Chaos Error" | Error message |
You can simulate different HTTP failures:
{
"type": "http_error",
"status": 401,
"message": "Unauthorized"
}or:
{
"type": "http_error",
"status": 503,
"message": "Service unavailable"
}Latency
Artificially delay a request before allowing it to continue to the real Express route.
{
"routes": {
"/api/users": {
"failure": {
"type": "latency",
"latencyMs": 3000
}
}
}
}The request flow becomes:
Client
↓
/api/users
↓
Chaos Route
↓
⏳ 3 seconds
↓
usersController
↓
ResponseOptions
| Option | Type | Default | Description |
| ----------- | ----------- | ------- | --------------------- |
| type | "latency" | — | Failure type |
| latencyMs | number | 3000 | Delay in milliseconds |
Timeout
Simulate a request that hangs for a specified duration and then terminates the connection.
{
"routes": {
"/api/users": {
"failure": {
"type": "timeout",
"timeoutMs": 3000
}
}
}
}A request to /api/users will hang for 3 seconds and then the connection will be terminated.
Options
| Option | Type | Default | Description |
| ----------- | ----------- | ------- | ---------------------------------------- |
| type | "timeout" | — | Failure type |
| timeoutMs | number | 5000 | Time before the connection is terminated |
Connection Error
Immediately terminate the connection to simulate a connection failure.
{
"routes": {
"/api/users": {
"failure": {
"type": "connection_error"
}
}
}
}A request to /api/users will have its connection terminated without receiving a response.
Options
| Option | Type | Default | Description |
| ------ | -------------------- | ------- | ------------ |
| type | "connection_error" | — | Failure type |
Rate Limit
Limit requests to an endpoint and return 429 when the limit is exceeded.
{
"routes": {
"/api/login": {
"failure": {
"type": "rate_limit",
"limit": 5,
"windowMs": 60000
}
}
}
}After 5 requests within 60 seconds, further requests will receive a 429 Too Many Requests response.
Options
| Option | Type | Default | Description |
| ---------- | -------------- | ------- | --------------------------- |
| type | "rate_limit" | — | Failure type |
| limit | number | 10 | Maximum requests allowed |
| windowMs | number | 60000 | Time window in milliseconds |
Request Manipulation
Modify, add, or remove request fields before they reach your controller.
{
"routes": {
"/api/profile": {
"request": {
"remove": ["email"],
"set": {
"age": 99
},
"add": {
"chaosTest": true
}
}
}
}
}Add Request Fields
Use add to add fields to the request.
"add": {
"chaosTest": true
}Modify Request Fields
Use set to modify existing request fields.
"set": {
"age": 99
}Remove Request Fields
Use remove to remove fields from the request.
"remove": ["email"]The modified request is then passed to your existing controller.
Response Manipulation
Modify, add, or remove response fields before they reach the client.
{
"routes": {
"/api/profile": {
"response": {
"remove": ["email"],
"set": {
"age": 99
},
"add": {
"chaosTest": true
}
}
}
}
}Add Response Fields
Use add to add fields to the response.
"add": {
"chaosTest": true
}Modify Response Fields
Use set to modify existing response fields.
"set": {
"age": 99
}Remove Response Fields
Use remove to remove fields from the response.
"remove": ["email"]The modified response is then sent to the client.
Multiple Routes
You can configure different failures for different endpoints.
{
"routes": {
"/api/login": {
"failure": {
"type": "http_error",
"status": 500,
"message": "Login service failed"
}
},
"/api/users": {
"failure": {
"type": "latency",
"latencyMs": 3000
}
}
}
}Now:
/api/login
↓
500 Error
/api/users
↓
3 second delay
↓
Normal controllerRoutes Without Chaos
Routes that aren't configured are completely unaffected.
For example:
{
"routes": {
"/api/login": {
"failure": {
"type": "http_error",
"status": 500
}
}
}
}A request to:
/api/productswill simply continue through Express normally.
/api/products
↓
Chaos Route
↓
next()
↓
productsControllerDisabling a Failure
Remove the failure configuration from the route:
{
"routes": {
"/api/login": {}
}
}You can also remove the route completely:
{
"routes": {}
}OR
Add this inside your .env
CHAOS="false"The request will pass through normally.
Configuration Reference
Current supported failure types:
| Failure | Description |
| ------------ | ----------------------------------- |
| http_error | Return a configured HTTP error |
| latency | Delay the request before continuing |
| connection_error | Destoy the connection |
| timeout | hangs req for specific period then terminates connection |
| rate_limit | Limit requests to an endpoint and return 429 when the limit is exceeded. |
Supported manipulation:
| type | Description |
| ------------ | ----------------------------------- |
| request | Modify, add, or remove request fields before they reach your controller. |
| response | Modify, add, or remove request fields before they reach to client. |
More failure types are planned as Chaos Route evolves.
Example Express Application
import express from "express";
import { chaos } from "@priyabrat/chaos-route";
const app = express();
app.use(express.json());
app.use(chaos());
app.post("/api/login", (req, res) => {
res.json({
message: "Login successful"
});
});
app.get("/api/users", (req, res) => {
res.json([
{ id: 1, name: "John" },
{ id: 2, name: "Jane" }
]);
});
app.listen(5000, () => {
console.log("Server running on port 5000");
});With:
{
"routes": {
"/api/login": {
"failure": {
"type": "http_error",
"status": 500,
"message": "Something went wrong"
}
},
"/api/users": {
"failure": {
"type": "latency",
"latencyMs": 5000
}
}
}
}You can test how your application handles both failures without changing either controller.
Version History
- Current
Request/Response Manipulation
Add request/response fields Modify request/response fields Remove request/response fields
Failure Injection
- [x] Timeout
- [x] Connection errors
- [x] Rate limiting (
429)
— Initial Release
- [x] HTTP errors
- [x] Latency injection
Important
Chaos Route is intended primarily for development and testing.
Avoid enabling failure configurations in production unless you explicitly understand the consequences.
A good practice is to use Chaos Route only in development/test environments.
Roadmap
Planned failure types and features include:
- [x] Timeout
- [x] Connection errors
- [x] Rate limiting (
429) - [ ] Custom responses
- [x] Request/response manipulation
- [x] Better configuration validation
- [x] Environment-based configuration
- [ ] More fault-injection strategies
Contributing
Contributions, ideas, bug reports, and feature requests are welcome.
If you find a bug or have an idea for a new failure type, open an issue or submit a pull request.
License
Built for developers who want to test what happens when their APIs don't behave perfectly.
