Request timeouts prevent long-running requests from consuming server resources indefinitely. The system implements configurable timeouts at both global and per-route levels.
REQUEST_TIMEOUT_MS=30000 # 30 seconds (default)All requests are subject to the global timeout unless overridden at the route level.
// Configured in src/index.ts
app.use(globalTimeout);
app.use(haltOnTimedout);Individual routes can override the global timeout:
import {
TimeoutPresets,
customTimeout,
haltOnTimedout,
} from "../middleware/timeout";
// Using presets
router.post("/quick-operation", TimeoutPresets.quick, haltOnTimedout, handler);
router.post(
"/standard-operation",
TimeoutPresets.standard,
haltOnTimedout,
handler,
);
router.post("/long-operation", TimeoutPresets.long, haltOnTimedout, handler);
router.post(
"/batch-operation",
TimeoutPresets.extended,
haltOnTimedout,
handler,
);
// Custom timeout
router.post("/custom", customTimeout(45000), haltOnTimedout, handler);| Preset | Duration | Use Case |
|---|---|---|
| quick | 5 seconds | Simple queries, health checks |
| standard | 30 seconds | Default operations |
| long | 60 seconds | Complex transactions, external API calls |
| extended | 2 minutes | Batch operations, reports |
When a request times out, the server returns:
{
"error": "Request Timeout",
"message": "The request took too long to process",
"code": "REQUEST_TIMEOUT"
}HTTP Status: 408 Request Timeout
app.use(timeout("30s")); // 1. Set timeout
app.use(haltOnTimedout); // 2. Check timeout before each middleware
app.use(express.json()); // 3. Your middleware
app.use(haltOnTimedout); // 4. Check timeout again
app.use("/api", routes); // 5. Routes
app.use(timeoutErrorHandler); // 6. Handle timeout errors
app.use(errorHandler); // 7. General error handlerThe haltOnTimedout middleware should be placed:
- After the timeout middleware
- Before route handlers
- Between middleware that might take time
This prevents timed-out requests from continuing through the middleware chain.
Timeout events are automatically logged with:
- HTTP method
- Request URL
- Client IP address
- Timestamp
Example log:
Request timeout: {
method: 'POST',
url: '/api/transactions/deposit',
ip: '192.168.1.100',
timestamp: '2026-03-23T10:30:45.123Z'
}
// Too short - may timeout legitimate requests
router.post("/complex", customTimeout(1000), handler); // ❌
// Appropriate - allows time for external APIs
router.post("/complex", customTimeout(60000), handler); // ✅try {
const response = await fetch("/api/transactions/deposit", {
method: "POST",
body: JSON.stringify(data),
headers: { "Content-Type": "application/json" },
});
if (response.status === 408) {
// Handle timeout
console.error("Request timed out, please try again");
}
} catch (error) {
console.error("Request failed:", error);
}export const handler = async (req: Request, res: Response) => {
const cleanup = () => {
// Release locks, close connections, etc.
};
req.on("timeout", cleanup);
try {
await processRequest(req);
res.json({ success: true });
} catch (error) {
cleanup();
throw error;
}
};Track timeout occurrences to identify:
- Routes that need longer timeouts
- Performance bottlenecks
- External API issues
// Long timeout for deposit (external API + blockchain)
router.post("/deposit", TimeoutPresets.long, haltOnTimedout, depositHandler);
// Long timeout for withdraw
router.post("/withdraw", TimeoutPresets.long, haltOnTimedout, withdrawHandler);
// Quick timeout for reads
router.get("/:id", TimeoutPresets.quick, haltOnTimedout, getTransactionHandler);// Very long operation
router.post(
"/batch-process",
customTimeout(180000),
haltOnTimedout,
batchHandler,
);
// Quick health check
router.get("/health", customTimeout(2000), haltOnTimedout, healthHandler);app.get(
"/test-timeout",
customTimeout(2000),
haltOnTimedout,
async (req, res) => {
// This will timeout after 2 seconds
await new Promise((resolve) => setTimeout(resolve, 5000));
res.json({ message: "This will never be sent" });
},
);# Should timeout after configured duration
curl -X POST http://localhost:3000/api/test-timeout- Increase
REQUEST_TIMEOUT_MSin .env - Use per-route timeout for specific endpoints
- Check for slow database queries or external APIs
- Verify timeout middleware is before route handlers
- Ensure
haltOnTimedoutis used after timeout middleware - Check middleware order in index.ts
- Ensure
timeoutErrorHandleris before general error handler - Verify response hasn't been sent before timeout
- Minimal overhead (< 1ms per request)
- Prevents resource exhaustion from hanging requests
- Improves overall system reliability
- Set conservative timeouts (30-60 seconds)
- Monitor timeout rates in logs
- Alert on high timeout rates (> 5%)
- Use longer timeouts for known slow operations
- Implement retry logic in clients for timeout errors