{"id":17636,"library":"express-service-readiness-middleware","title":"Express Service Readiness Middleware","description":"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.","status":"active","version":"1.0.25","language":"javascript","source_language":"en","source_url":"git://github.com/croweman/express-service-readiness-middleware","tags":["javascript","express","readiness","dependencies","typescript"],"install":[{"cmd":"npm install express-service-readiness-middleware","lang":"bash","label":"npm"},{"cmd":"yarn add express-service-readiness-middleware","lang":"bash","label":"yarn"},{"cmd":"pnpm add express-service-readiness-middleware","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"ESM import is recommended for modern Node.js and TypeScript projects. While `require()` works for CommonJS, it's considered 'wrong' in ESM-first environments.","wrong":"const { createReadinessMiddleware } = require('express-service-readiness-middleware');","symbol":"createReadinessMiddleware","correct":"import { createReadinessMiddleware } from 'express-service-readiness-middleware';"},{"note":"Used for on-demand health checks of all configured dependencies. Returns a Promise.","wrong":"const { checkDependenciesHealth } = require('express-service-readiness-middleware');","symbol":"checkDependenciesHealth","correct":"import { checkDependenciesHealth } from 'express-service-readiness-middleware';"},{"note":"Provides a simple boolean check for whether all critical dependencies have achieved readiness.","wrong":"const { criticalDependenciesReady } = require('express-service-readiness-middleware');","symbol":"criticalDependenciesReady","correct":"import { criticalDependenciesReady } from 'express-service-readiness-middleware';"},{"note":"Essential for enabling internal logging, as no logger is set by default. The provided logger object must have a `log` function.","wrong":"const { setLogger } = require('express-service-readiness-middleware');","symbol":"setLogger","correct":"import { setLogger } from 'express-service-readiness-middleware';"}],"quickstart":{"code":"import express from 'express';\nimport { createReadinessMiddleware, setLogger, checkDependenciesHealth } from 'express-service-readiness-middleware';\n\nconst app = express();\nconst PORT = process.env.PORT || 3000;\n\n// Set a logger for internal messages (optional, but recommended)\nsetLogger(console);\n\n// Simulate a critical database dependency\nlet isDatabaseReady = false;\nsetTimeout(() => {\n  console.log('Database became ready after 5 seconds.');\n  isDatabaseReady = true;\n}, 5000);\n\n// Simulate a non-critical cache dependency that might fail initially\nlet isCacheHealthy = true;\nconst toggleCacheHealth = () => {\n  isCacheHealthy = !isCacheHealthy;\n  console.log(`Cache is now ${isCacheHealthy ? 'healthy' : 'unhealthy'}.`);\n};\nsetInterval(toggleCacheHealth, 15000);\n\nconst dependencies = [\n  {\n    name: 'database',\n    critical: true,\n    isReady: () => Promise.resolve(isDatabaseReady),\n    isHealthy: () => Promise.resolve(isDatabaseReady) // For liveness, same as readiness here\n  },\n  {\n    name: 'cache',\n    critical: false,\n    isReady: () => Promise.resolve(true), // Cache doesn't block readiness\n    isHealthy: () => Promise.resolve(isCacheHealthy) // Its health can fluctuate\n  }\n];\n\n// Register the readiness middleware before other routes\n// Requests to non-whitelisted paths will get 502 until 'database' is ready.\napp.use(createReadinessMiddleware(dependencies, { \n  whitelistedPaths: ['/liveness', '/ready'] \n}));\n\n// Liveness endpoint (always accessible)\napp.get('/liveness', (req, res) => {\n  res.status(200).send('Service is live');\n});\n\n// Readiness endpoint (checks current readiness status dynamically)\napp.get('/ready', async (req, res) => {\n  const health = await checkDependenciesHealth(dependencies);\n  if (health.allCriticalDependenciesHealthy) {\n    res.status(200).json({ status: 'ready', details: health });\n  } else {\n    res.status(503).json({ status: 'not ready', details: health });\n  }\n});\n\n// Application routes (will be gated by readiness middleware)\napp.get('/', (req, res) => {\n  res.send('Hello from the ready service!');\n});\n\n// Start the server\napp.listen(PORT, () => {\n  console.log(`Server listening on port ${PORT}`);\n  console.log('Try accessing / and /liveness immediately, then / after 5 seconds.');\n});","lang":"typescript","description":"Demonstrates setting up an Express application with readiness middleware. It includes critical and non-critical dependencies, whitelisted paths, and endpoints for both liveness and readiness, highlighting the middleware's gating behavior during startup."},"warnings":[{"fix":"If continuous health monitoring (liveness) is required, implement a separate liveness endpoint using `checkDependenciesHealth` that responds dynamically to current dependency health.","message":"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.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Call `setLogger(console)` or provide a compatible logger object (one with a `log` method) early in your application's bootstrap process.","message":"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.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Implement `isReady` and `isHealthy` functions to always return a Promise, handling any potential errors by resolving to `false` or ensuring the promise rejection is caught and processed gracefully within the middleware's logic.","message":"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.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"If your project is configured for ESM, use `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`.","cause":"This error typically occurs when attempting to `require()` an ESM-first package in a CommonJS context, or using incorrect import syntax for named exports. While the package ships types, the example in the README uses CommonJS `require()` which might conflict with an ESM-configured project (e.g., `\"type\": \"module\"` in `package.json`).","error":"TypeError: (0 , express_service_readiness_middleware_1.createReadinessMiddleware) is not a function"},{"fix":"Ensure all objects in the `dependencies` array have an `isReady` property set to an asynchronous function that returns a `Promise<boolean>`, e.g., `isReady: () => Promise.resolve(true)`.","cause":"A dependency object provided to `createReadinessMiddleware` or `checkDependenciesHealth` is missing the `isReady` property, or its value is not a function that returns a Promise.","error":"TypeError: dependency.isReady is not a function"},{"fix":"Inspect the `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.","cause":"The critical dependencies' `isReady` functions are consistently returning `false` or taking longer than `maximumWaitTimeForServiceReadinessInMilliseconds` to resolve to `true`, preventing the service from transitioning to a 'ready' state.","error":"Service is not becoming ready (502 errors persist)"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}