Skip to main content
current (v2.x.x)

Upgrading to v2.2.x

2.2.0โ€‹

Applies to: Upgrading from v2.0.x or v2.1.x to v2.2.x

Version 2.2.0 introduces first-class integration of the standalone HealthzServer into ExpressServer. This replaces the legacy Express-mounted health check routes with dedicated, isolated Kubernetes health probe endpoints (/healthz, /readyz, /startupz) running on a dedicated port (default 8282), avoiding probe timeouts caused by application event-loop load or request queue saturation.


๐ŸŽฏ Quick Summaryโ€‹

  • Primary Change: ExpressServer no longer mounts /healthz directly onto the Express application. Health probes are now managed via the dedicated HealthzServer on an isolated port (default 8282).
  • Configuration Update: withHealthCheck() and config.healthCheck are replaced with enableHealthzServer() / withHealthzServer() and config.healthzServer.
  • Readiness Probes: server.registerHealthCheck(name, fn, options) now maps checks to HealthzServer probes, defaulting to the 'readiness' probe.
  • Synchronous Readiness Query: server.ready() is now a synchronous boolean method (along with server.isReady()), reflecting whether the service is accepting traffic.
  • Estimated migration time: 5-10 minutes.

โš ๏ธ Breaking Changes & Migrationsโ€‹

1. ServerConfigBuilder Methodsโ€‹

The legacy .withHealthCheck() method has been replaced with dedicated Healthz server configuration helpers:

// Old (v2.0 / v2.1)
const config = new ServerConfigBuilder()
.withPort(3000)
.withHealthCheck({ path: '/healthz', detailed: true })
.build();

// New (v2.2.0+)
const config = new ServerConfigBuilder()
.withPort(3000)
.enableHealthzServer({ port: 8282 })
// or: .withHealthzServer({ port: 8282, shutdownDelayMs: 5000 })
.build();

To disable the Healthz probe server:

// Old
builder.disableHealthCheck();

// New
builder.disableHealthzServer();

2. Express Server Health Route Removalโ€‹

ExpressServer no longer exposes a /healthz route on the main application port. If your Kubernetes deployments, Docker compose setups, or load balancers were probing http://localhost:3000/healthz, update your probe configurations to target the dedicated Healthz probe port:

# Old Kubernetes probe configuration (on app port 3000)
livenessProbe:
httpGet:
path: /healthz
port: 3000

# New Kubernetes probe configuration (on healthz port 8282)
livenessProbe:
httpGet:
path: /healthz
port: 8282
readinessProbe:
httpGet:
path: /readyz
port: 8282
startupProbe:
httpGet:
path: /startupz
port: 8282

3. Server Configuration Object (CatbeeServerConfig)โ€‹

The healthCheck property and skipHealthzChecksValidation have been removed from CatbeeServerConfig and replaced with healthzServer:

// Old (v2.0 / v2.1)
const server = new ExpressServer({
port: 3000,
healthCheck: {
path: '/healthz',
detailed: true
}
});

// New (v2.2.0+)
const server = new ExpressServer({
port: 3000,
healthzServer: {
enable: true,
port: 8282,
shutdownDelayMs: 5000
}
});

4. server.registerHealthCheck() Enhancementsโ€‹

registerHealthCheck() now accepts target probe options ('readiness', 'liveness', or 'both', defaulting to 'readiness'), and check functions receive an optional AbortSignal:

// Old
server.registerHealthCheck('db', async () => await checkDb());

// New
server.registerHealthCheck('db', async (signal) => {
return await db.ping({ signal });
}, 'readiness'); // Defaults to 'readiness'

5. server.ready() is Synchronousโ€‹

server.ready() previously executed health checks asynchronously and returned Promise<boolean>. In v2.2.0, server.ready() synchronously returns the current readiness flag (boolean) matching server.isReady():

// Old
const isReady = await server.ready();

// New
const isReady = server.ready(); // or server.isReady()

6. Environment Variablesโ€‹

The legacy server-level health check environment variables have been replaced with dedicated Healthz server environment variables:

Old VariableNew Variable / Replacement
SERVER_HEALTH_CHECK_PATHHEALTHZ_PATH (fallback: SERVER_HEALTHZ_PATH)
SERVER_HEALTH_CHECK_DETAILED_OUTPUTHEALTHZ_DETAILED (fallback: SERVER_HEALTHZ_DETAILED)
SERVER_HEALTH_CHECK_WITH_GLOBAL_PREFIX(Removed; HealthzServer runs on its own port and does not use route prefix)
SERVER_SKIP_HEALTHZ_CHECKS_VALIDATION(Removed; control readiness via server.setReady() or readiness probe config)
(None)SERVER_HEALTHZ_ENABLE or HEALTHZ_ENABLE (toggle HealthzServer in ExpressServer)
(None)HEALTHZ_PORT or SERVER_HEALTHZ_PORT (dedicated probe server port)
(None)HEALTHZ_READYZ_PATH or SERVER_READYZ_PATH (default /readyz)
(None)HEALTHZ_STARTUPZ_PATH or SERVER_STARTUPZ_PATH (default /startupz)
(None)HEALTHZ_SHUTDOWN_DELAY_MS or SERVER_HEALTHZ_SHUTDOWN_DELAY_MS (LB drain delay)
(None)HEALTHZ_CHECK_TIMEOUT_MS or SERVER_HEALTHZ_CHECK_TIMEOUT_MS (check timeout)

7. Decoupled Startup State & Pre-binding Probe Bootโ€‹

  • Probe Server Starts Before Listen: HealthzServer begins listening on its port before Express binds or runs beforeStart hooks, allowing /healthz to return 200 OK while /startupz and /readyz accurately return 503 Service Unavailable.
  • Decoupled Startup State: /startupz returns 503 Service Unavailable until application startup completes. ExpressServer automatically invokes server.markStartupComplete() once listening.
  • Probe Resilience: When service readiness transitions to false (during graceful shutdown draining or temporary dependency outages), startupComplete remains true and /startupz stays 200 OK, preventing Kubernetes from triggering startup probe failures or kill loops.
  • Method Renames: HealthzServer.isStarted() has been replaced by HealthzServer.isRunning(). New methods markStartupComplete() and isStartupComplete() are available on both HealthzServer and ExpressServer.