# Health check endpoint exists, returns HTTP 200, verifies critical dependencies, and consumed by load balancer

- **Pattern:** `ab-000987` (`deployment-readiness.environment-configuration.health-check`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000987
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000987)

## Why it matters

A health check endpoint that only returns HTTP 200 without verifying the database or downstream services will report healthy during a database connection pool exhaustion or broken third-party integration — exactly the conditions that cause user-facing failures. NIST SI-6 requires software verification; ISO 25010 reliability.availability requires accurate system state reporting. A load balancer routing traffic to a broken instance that reports itself healthy multiplies the failure, not the resilience. The health endpoint is the contract between your application and its infrastructure.

## Severity rationale

Low because a shallow health check returns false positives under partial failures, causing load balancers to route to unhealthy instances rather than triggering failover — the gap is only realized during compound failures.

## Remediation

Create an `/api/health` route that verifies your critical dependencies before returning 200.

```ts
// src/app/api/health/route.ts
import { NextResponse } from 'next/server';
import { createClient } from '@/lib/supabase/server';

export async function GET() {
  try {
    const supabase = createClient();
    await supabase.from('_health').select('1').single(); // lightweight DB probe
    return NextResponse.json({ status: 'healthy' }, { status: 200 });
  } catch (err) {
    return NextResponse.json(
      { status: 'unhealthy', error: (err as Error).message },
      { status: 503 }
    );
  }
}
```

Then configure your platform to use it:
- AWS ALB: Target Group → Health check path: `/api/health`
- Kubernetes: `livenessProbe.httpGet.path: /api/health`
- Vercel: no native load balancer health check, but use Uptime Robot against this endpoint

## Detection

- **ID:** `health-check`
- **Severity:** `low`
- **What to look for:** Enumerate every relevant item. Look for a health check endpoint (typically at `/health`, `/api/health`, `/healthz`, or `/status`). Check if it returns HTTP 200 when healthy. Verify it checks critical dependencies (database connection, external API connectivity). Confirm the load balancer or orchestration platform (Kubernetes, AWS ALB, Vercel) is configured to consume this endpoint.
- **Pass criteria:** At least 1 of the following conditions is met. A health check endpoint exists at a standard path. It returns HTTP 200 when healthy. It checks critical dependencies. The load balancer or orchestration consumes it.
- **Fail criteria:** No health check endpoint found, or endpoint doesn't verify dependencies, or platform isn't configured to use it.
- **Skip (N/A) when:** The project doesn't run on a load-balanced platform.
- **Detail on fail:** `"No /health endpoint found in application routes."` or `"/health endpoint exists but only returns 200, does not verify database connectivity."` or `"Health endpoint exists but load balancer is not configured to use it."`
- **Remediation:** Add a health check endpoint. For Next.js:

  ```ts
  // app/api/health/route.ts
  import { NextResponse } from 'next/server';

  export async function GET() {
    try {
      // Check database
      const db = await getDatabase();
      await db.query('SELECT 1');

      // Check critical external service
      const response = await fetch('https://api.external-service.com/health', {
        timeout: 5000
      });
      if (!response.ok) throw new Error('External API down');

      return NextResponse.json({ status: 'healthy' }, { status: 200 });
    } catch (error) {
      return NextResponse.json(
        { status: 'unhealthy', error: error.message },
        { status: 503 }
      );
    }
  }
  ```

  Then configure load balancer to check this endpoint:
  - Vercel: Add health check in vercel.json or dashboard
  - AWS ALB: Target group → Health check settings → Path: `/api/health`
  - Kubernetes: Add liveness probe in deployment manifest

## External references

- iso-25010 reliability.availability
- nist SI-6

Taxons: error-resilience

HTML version: https://auditbuffet.com/patterns/ab-000987
