Express Service Readiness Middleware
raw JSON →This module provides Express.js middleware for determining whether server routes should be exposed based on the health status of critical service dependencies. Currently stable at version 1.0.25, the package is typically updated for bug fixes and compatibility with new Express.js versions. A key differentiator is its focus on *readiness* at startup rather than continuous *liveness* monitoring. Once the service achieves a 'ready' state, it maintains this status for its lifetime, meaning subsequent failures of critical dependencies will *not* revert it to an 'unready' state and block non-whitelisted routes. It returns a 502 status code for non-whitelisted routes when critical dependencies are not ready, and allows specific paths to be whitelisted for access even during unready periods. It distinguishes between critical and non-critical dependencies, allowing flexible health definitions.
Common errors
error TypeError: (0 , express_service_readiness_middleware_1.createReadinessMiddleware) is not a function ↓
import { createReadinessMiddleware } from 'express-service-readiness-middleware';. If strictly using CommonJS and facing this issue, ensure your tsconfig.json (if applicable) and build setup correctly target CommonJS modules, or explicitly set "type": "commonjs" in your package.json. error TypeError: dependency.isReady is not a function ↓
dependencies array have an isReady property set to an asynchronous function that returns a Promise<boolean>, e.g., isReady: () => Promise.resolve(true). error Service is not becoming ready (502 errors persist) ↓
isReady implementations for your critical dependencies. Check external services, database connections, or other resources. Consider temporarily increasing maximumWaitTimeForServiceReadinessInMilliseconds in the middleware configuration for debugging, and ensure your setLogger is configured to view readiness logs. Warnings
gotcha This middleware implements a 'readiness' check, not a continuous 'liveness' check. Once the service's critical dependencies are initially deemed ready, the service will remain 'ready' for its lifetime. Subsequent failures of critical dependencies will NOT revert the service to an 'unready' state or block non-whitelisted routes, as it would with a liveness probe. This design choice may differ from expectations for ongoing health monitoring. ↓
gotcha No informational logging will occur internally unless a logger is explicitly set using the `setLogger` function. This can make debugging readiness issues challenging if logging is not configured. ↓
gotcha The `isReady` and `isHealthy` functions provided in dependency objects must return Promises. If these promises reject due to an error, they are treated as the dependency *not* being ready/healthy. Ensure robust error handling within these promise-returning functions to accurately reflect dependency status. ↓
Install
npm install express-service-readiness-middleware yarn add express-service-readiness-middleware pnpm add express-service-readiness-middleware Imports
- createReadinessMiddleware wrong
const { createReadinessMiddleware } = require('express-service-readiness-middleware');correctimport { createReadinessMiddleware } from 'express-service-readiness-middleware'; - checkDependenciesHealth wrong
const { checkDependenciesHealth } = require('express-service-readiness-middleware');correctimport { checkDependenciesHealth } from 'express-service-readiness-middleware'; - criticalDependenciesReady wrong
const { criticalDependenciesReady } = require('express-service-readiness-middleware');correctimport { criticalDependenciesReady } from 'express-service-readiness-middleware'; - setLogger wrong
const { setLogger } = require('express-service-readiness-middleware');correctimport { setLogger } from 'express-service-readiness-middleware';
Quickstart
import express from 'express';
import { createReadinessMiddleware, setLogger, checkDependenciesHealth } from 'express-service-readiness-middleware';
const app = express();
const PORT = process.env.PORT || 3000;
// Set a logger for internal messages (optional, but recommended)
setLogger(console);
// Simulate a critical database dependency
let isDatabaseReady = false;
setTimeout(() => {
console.log('Database became ready after 5 seconds.');
isDatabaseReady = true;
}, 5000);
// Simulate a non-critical cache dependency that might fail initially
let isCacheHealthy = true;
const toggleCacheHealth = () => {
isCacheHealthy = !isCacheHealthy;
console.log(`Cache is now ${isCacheHealthy ? 'healthy' : 'unhealthy'}.`);
};
setInterval(toggleCacheHealth, 15000);
const dependencies = [
{
name: 'database',
critical: true,
isReady: () => Promise.resolve(isDatabaseReady),
isHealthy: () => Promise.resolve(isDatabaseReady) // For liveness, same as readiness here
},
{
name: 'cache',
critical: false,
isReady: () => Promise.resolve(true), // Cache doesn't block readiness
isHealthy: () => Promise.resolve(isCacheHealthy) // Its health can fluctuate
}
];
// Register the readiness middleware before other routes
// Requests to non-whitelisted paths will get 502 until 'database' is ready.
app.use(createReadinessMiddleware(dependencies, {
whitelistedPaths: ['/liveness', '/ready']
}));
// Liveness endpoint (always accessible)
app.get('/liveness', (req, res) => {
res.status(200).send('Service is live');
});
// Readiness endpoint (checks current readiness status dynamically)
app.get('/ready', async (req, res) => {
const health = await checkDependenciesHealth(dependencies);
if (health.allCriticalDependenciesHealthy) {
res.status(200).json({ status: 'ready', details: health });
} else {
res.status(503).json({ status: 'not ready', details: health });
}
});
// Application routes (will be gated by readiness middleware)
app.get('/', (req, res) => {
res.send('Hello from the ready service!');
});
// Start the server
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`);
console.log('Try accessing / and /liveness immediately, then / after 5 seconds.');
});