Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
World desk7 min

Implementing Degraded Node.js Health Checks for API Credentials and Tiers

Liveness should detect stuck processes, readiness should detect inability to serve, and degraded state should cover reduced service. Here is how to apply that to API credentials and service tiers in Node.js.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A single customer’s invalid, expired, or revoked credential should not make a Node.js API unhealthy. Liveness should answer “is this process stuck?”, readiness should answer “can this instance serve the traffic it is meant to receive right now?”, and a degraded state should describe an instance that is still serving a defined subset of its work. Where a credential or tier condition falls among those three depends on your API contract. Kubernetes and framework probe documentation explain how probes behave, but they do not decide which credential or tier states count as degraded for your service.

Liveness and readiness trigger different consequences

Kubernetes uses a liveness probe to decide when to restart a container, and a readiness probe to decide whether a Pod should receive traffic from a Service. The two outcomes have very different costs. A restart drops in-flight requests and resets in-memory caches and connection pools. Removing a Pod from rotation only moves its load to its neighbours, and the Pod can rejoin as soon as it passes again.

As an Amazon Associate I earn from qualifying purchases.

Probe Question it answers Failure consequence in Kubernetes Belongs here
Startup Has initialization finished? When configured, liveness and readiness checks do not run until startup succeeds Slow configuration load, cache warm-up
Liveness Is the process stuck or unable to make progress? The container is restarted Deadlocked event loop, unrecoverable internal state
Readiness Can this instance serve the traffic it is meant to receive now? The Pod is removed from Service endpoints until it passes again Required database, required credential store, graceful shutdown

The Express documentation, in its “Health Checks and Graceful Shutdown” guidance, states the load-balancer view directly: “A load balancer uses health checks to determine if an application instance is healthy and can accept requests.” That is a readiness question. Most credential and tier problems are readiness-shaped at most, and many are not health problems at all.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Define the states before writing the endpoint

Write the state model in terms of your API’s promises first. The HTTP representation can come later, and it should stay small.

  1. List each request class the API serves, and the tier or credential type allowed to call it.
  2. Mark each dependency as required (no useful work is possible without it) or optional (only one request class needs it).
  3. Map required dependencies to readiness. Keep liveness free of dependency checks.
  4. For each optional failure, decide whether the instance should report degraded while still returning success to probes, or whether only the affected routes should return an error.
  5. Decide that caller-level credential results never change probe status.

In practice this produces three operator-facing states:

  • Live: the process can make progress. A failure means a restart is a plausible recovery.
  • Ready: every required dependency is available, so the instance can accept its intended traffic.
  • Degraded: the instance is ready, but at least one optional capability is impaired. Affected requests fail with a precise status, and everything else continues.

Should an invalid API credential make a service unhealthy?

Usually not. An invalid, expired, revoked, or quota-exhausted key describes one caller’s request. The correct response is a 401, 403, or 429 for that request, and the instance keeps serving everyone else. If a bad key changed probe results, one client could remove capacity from all clients, and a restart would not fix anything.

The exception is when the credential machinery is required for every request. If each call must verify a key against a credential store, and that store is unreachable with no usable cached verification, the instance cannot do its intended work. Readiness should then fail. That is a dependency outage, not a bad key, and the probe reason should say so.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Separate caller outcomes from dependency outcomes

  • Caller outcome (key invalid, revoked, expired, or over quota): return the request-level status, log a redacted reason, and leave probes unchanged.
  • Dependency outcome (credential store or issuer unreachable): readiness depends on whether cached or fresh verification can still satisfy required requests. Liveness is unaffected.

How readiness should handle service tiers

Tier entitlements are a per-request decision. Readiness should reflect whether the instance can serve the requests it is meant to receive, not whether every tier’s features are working. If a premium-only capability depends on a failing service, baseline callers should still be served. Marking the whole instance unready removes capacity from requests that never touch the failed feature.

The table below shows one way to classify common states. It is an example starting point for a hypothetical API, not a standard, and each row should be replaced with your own contract.

Condition Liveness Readiness Response to affected requests Reported state
A caller’s key is expired or revoked Pass Pass 401 or 403 for that key ok
A caller’s tier lacks entitlement for an endpoint Pass Pass 403 for that call ok
A caller has exhausted its quota Pass Pass 429 for that caller ok
A premium-only dependency is down, baseline traffic still works Pass Pass 503 on premium routes only degraded
A required database is down Pass Fail Pod removed from Service endpoints unavailable
Credential store unreachable, no usable cache, every call needs verification Pass Fail 503 on all authenticated calls unavailable
Event loop stalled or internal state unrecoverable Fail Fail Container restarted; no response is possible not reported

Keep tier logic out of the probe itself where possible. A readiness check that asks “is the premium analytics client healthy?” couples every tier to one optional capability. A check that asks “are the required dependencies for baseline requests available?” keeps probe results aligned with capacity.

Implement the endpoints in Node.js

The Node.js Reference Architecture’s health-check guidance recommends a minimal implementation for most services, with Express examples that expose /livez and /readyz routes. The sketch below follows that approach and adds the degraded state. It is illustrative and has not been run or load-tested. Replace the placeholder dependency checks with your own.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const express = require('express');

const app = express();
const PORT = process.env.PORT || 3000;

// Dependency state is refreshed in the background so probe requests stay cheap.
const health = {
  required: { database: false, credentialStore: false },
  optional: { premiumAnalytics: false },
  draining: false,
};

async function refreshHealth() {
  health.required.database = await checkDatabase().then(() => true, () => false);
  health.required.credentialStore = await checkCredentialStore().then(() => true, () => false);
  health.optional.premiumAnalytics = await checkAnalytics().then(() => true, () => false);
}

refreshHealth();
setInterval(refreshHealth, 10000).unref();

process.on('SIGTERM', () => {
  health.draining = true;
});

app.get('/livez', (req, res) => {
  res.status(200).type('text/plain').send('ok');
});

app.get('/readyz', (req, res) => {
  const requiredOk = Object.values(health.required).every(Boolean);
  if (health.draining || !requiredOk) {
    return res.status(503).json({ status: 'unavailable' });
  }
  const optionalOk = Object.values(health.optional).every(Boolean);
  res.status(200).json({ status: optionalOk ? 'ok' : 'degraded' });
});

app.listen(PORT);

What this sketch does

  • Liveness never calls a dependency, so a database or credential outage cannot restart the process.
  • Readiness is false until the first refresh completes, which prevents traffic from reaching an instance that has not checked its dependencies.
  • Draining on SIGTERM removes the instance from rotation before shutdown.
  • Optional failures return 200 with degraded, so the Pod stays in rotation. Routes that need the optional capability must still return their own error.

Wire each route that depends on an optional capability to check that capability directly. The probe status does not protect those routes on its own.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Configure Kubernetes probes to match the routes

Probe paths must match routes your application actually exposes. The values below are starting points to tune against your own startup time and failure tolerance, not tested recommendations.

startupProbe:
  httpGet:
    path: /livez
    port: 3000
  periodSeconds: 5
  failureThreshold: 12
livenessProbe:
  httpGet:
    path: /livez
    port: 3000
  periodSeconds: 10
  failureThreshold: 3
readinessProbe:
  httpGet:
    path: /readyz
    port: 3000
  periodSeconds: 5
  failureThreshold: 2

Kubernetes evaluates the HTTP status code, not the response body. Under this configuration, a degraded response is invisible to the Service and visible only to anything that reads the body.

Report degradation without leaking secrets

NestJS Terminus, in its documentation on health checks, shows one framework pattern: a degraded indicator does not fail the check. It is listed under info, the overall status becomes degraded, and the HTTP status stays 200. That pattern works only if your probe consumer ignores bodies. Verify how your load balancer or orchestrator interprets status codes before adopting it on a probe endpoint.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Keep the probe response to a status word. If operators need dependency names or timings, expose them on a separate authenticated route with its own access controls. Never include raw credential values, authorization headers, key identifiers that let someone impersonate a caller, or stack traces in a health response or its logs. Log the reason for a failed verification as a redacted category, such as “key expired” or “store timeout.”

Lightship is one documented Node.js library that provides readiness, liveness, startup checks, and graceful shutdown. Using a library makes sense when its state model matches yours. If it does not, a few routes are usually easier to reason about than a framework’s default categories.

Troubleshoot common failure patterns

  • Pods restart during a database outage: a dependency check has leaked into liveness. Move it to readiness.
  • Pods flap in and out of the Service: an optional or slow dependency is driving readiness, or the timeout is shorter than the dependency’s normal latency. Raise failureThreshold or refresh in the background as shown above.
  • All Pods become unready after one customer’s key is revoked: a caller-level result is reaching the probe state. Return the status from the request handler instead.
  • Degraded state never shows up in the load balancer: expected when the probe ignores response bodies. Scrape the body with monitoring or use a separate route.
  • Probes pass but customers receive 503 responses: the route that uses the failing capability does not check that capability. Add a route-level check or error path.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.