Skip to content

Endpoints de Health Check

Visao Geral

O ProCases expoe 3 endpoints de health check publicos (sem autenticacao) para monitoramento e orquestracao de containers. Esses endpoints sao usados por Kubernetes, Docker Compose health checks, load balancers e sistemas de monitoramento (Prometheus/Grafana) para verificar se a aplicacao esta saudavel, pronta e viva.


Arquitetura de Arquivos

CamadaArquivoResponsabilidade
Presentationsrc/presentation/controllers/health.controller.tsController com 3 endpoints
Configsrc/app.module.tsRegistro do controller

O controller e marcado com @Public() no nivel de classe, tornando todos os seus endpoints acessiveis sem autenticacao.


Controller Completo

typescript
@ApiTags('Health')
@Controller('health')
@Public()
export class HealthController {
  @Get()
  @ApiOperation({
    summary: 'Health check',
    description: 'Check if the API is running and healthy',
  })
  @ApiResponse({
    status: 200,
    description: 'API is healthy',
    schema: {
      type: 'object',
      properties: {
        status: { type: 'string', example: 'ok' },
        timestamp: { type: 'string', example: '2025-01-28T12:00:00.000Z' },
        uptime: { type: 'number', example: 12345.678 },
      },
    },
  })
  check() {
    return {
      status: 'ok :D',
      timestamp: new Date().toISOString(),
      uptime: process.uptime(),
    };
  }

  @Get('ready')
  @ApiOperation({
    summary: 'Readiness check',
    description: 'Check if the API is ready to receive requests',
  })
  @ApiResponse({
    status: 200,
    description: 'API is ready',
    schema: {
      type: 'object',
      properties: {
        status: { type: 'string', example: 'ready' },
      },
    },
  })
  ready() {
    return {
      status: 'ready',
    };
  }

  @Get('live')
  @ApiOperation({
    summary: 'Liveness check',
    description: 'Check if the API is alive',
  })
  @ApiResponse({
    status: 200,
    description: 'API is alive',
    schema: {
      type: 'object',
      properties: {
        status: { type: 'string', example: 'alive' },
      },
    },
  })
  live() {
    return {
      status: 'alive',
    };
  }
}

Endpoints

GET /health

Health check principal. Retorna o status da API, timestamp atual e uptime do processo.

Autenticacao: Nenhuma (@Public())

Response (200):

typescript
{
  status: "ok :D",              // Status fixo
  timestamp: string,            // ISO 8601 (ex: "2025-06-15T14:30:00.000Z")
  uptime: number               // Segundos desde o inicio do processo
}

Exemplo de response:

json
{
  "status": "ok :D",
  "timestamp": "2025-06-15T14:30:00.000Z",
  "uptime": 86432.159
}

Campos:

CampoTipoDescricao
statusstringSempre "ok :D" se o processo esta rodando
timestampstringData/hora atual do servidor em ISO 8601
uptimenumberTempo em segundos desde o process.start (inclui fracionario)

Uso principal: Verificacao geral de que a API esta respondendo. Se este endpoint retornar 200, o processo Node.js esta ativo e o framework NestJS/Fastify esta funcional.

process.uptime(): Retorna o numero de segundos desde que o processo Node.js foi iniciado. Util para detectar reinicializacoes inesperadas -- se o uptime e muito baixo, o processo pode ter crashado e reiniciado.


GET /health/ready

Readiness probe. Indica se a API esta pronta para receber requisicoes de usuarios.

Autenticacao: Nenhuma (@Public())

Response (200):

typescript
{
  status: "ready"
}

Exemplo de response:

json
{
  "status": "ready"
}

Uso em Kubernetes:

yaml
readinessProbe:
  httpGet:
    path: /health/ready
    port: 3000
  initialDelaySeconds: 10
  periodSeconds: 5
  failureThreshold: 3

Semantica: No padrao Kubernetes, o readiness probe determina se o pod deve receber trafico do Service. Se o readiness falhar, o pod e removido do pool de endpoints (mas continua rodando).

Implementacao atual: Retorna { status: 'ready' } incondicionalmente. Em uma implementacao mais robusta, poderia verificar conexoes com banco de dados, Redis e outros servicos antes de declarar readiness.

Possivel evolucao futura:

typescript
async ready() {
  const dbOk = await this.checkDatabase();
  const redisOk = await this.checkRedis();

  if (!dbOk || !redisOk) {
    throw new ServiceUnavailableException('Not ready');
  }

  return { status: 'ready', database: dbOk, redis: redisOk };
}

GET /health/live

Liveness probe. Indica se o processo esta vivo.

Autenticacao: Nenhuma (@Public())

Response (200):

typescript
{
  status: "alive"
}

Exemplo de response:

json
{
  "status": "alive"
}

Uso em Kubernetes:

yaml
livenessProbe:
  httpGet:
    path: /health/live
    port: 3000
  initialDelaySeconds: 30
  periodSeconds: 10
  failureThreshold: 3

Semantica: No padrao Kubernetes, o liveness probe determina se o pod precisa ser reiniciado. Se o liveness falhar, o Kubernetes mata o pod e cria um novo.

Implementacao atual: Retorna { status: 'alive' } incondicionalmente. O simples fato de responder HTTP 200 ja prova que o processo esta vivo.


Diferencas entre os 3 Endpoints

EndpointPropositoQuando FalharAcao do Orchestrator
/healthVerificacao geralProcesso crashouAlertar operadores
/health/readyPronto para traficoDependencias indisponiveisRemover do pool
/health/liveProcesso vivoDeadlock/hangReiniciar pod

Fluxo tipico de startup:

1. Pod inicia
2. /health/live responde 200 (processo vivo, nao reiniciar)
3. App conecta ao banco, Redis, etc.
4. /health/ready responde 200 (pode receber trafico)
5. Load balancer adiciona ao pool

Fluxo de degradacao:

1. Banco de dados cai
2. /health/live continua 200 (processo vivo)
3. /health/ready deveria retornar 503 (nao pronto)
4. Load balancer remove do pool
5. Sem reinicializacao desnecessaria

Decorator @Public()

Todos os endpoints de health sao publicos:

typescript
@Controller('health')
@Public()
export class HealthController {

O decorator @Public() e aplicado no nivel da classe, marcando todos os endpoints do controller como acessiveis sem sessao. O AuthGuard global verifica esse decorator e ignora a autenticacao quando presente.

Isso e essencial porque:

  1. Health checks sao chamados por sistemas automatizados (Kubernetes, Prometheus)
  2. Esses sistemas nao possuem sessao ou cookies
  3. Os endpoints nao expoe dados sensiveis

Configuracao Docker Compose

yaml
services:
  api:
    image: procases-api
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

O start_period permite que a aplicacao tenha tempo de inicializar antes de comecar a verificar health.


Configuracao Kubernetes

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: procases-api
spec:
  template:
    spec:
      containers:
        - name: api
          ports:
            - containerPort: 3000
          livenessProbe:
            httpGet:
              path: /health/live
              port: 3000
            initialDelaySeconds: 30
            periodSeconds: 10
            failureThreshold: 3
          readinessProbe:
            httpGet:
              path: /health/ready
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 5
            failureThreshold: 3
          startupProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 5
            failureThreshold: 30

startupProbe: Usado durante o boot inicial. Permite ate 150 segundos (30 * 5s) para a aplicacao iniciar antes de comecar os outros probes.


Configuracao Nginx

Para load balancers Nginx, o health check pode ser usado como upstream check:

nginx
upstream api_backend {
    server api1:3000;
    server api2:3000;
}

server {
    location /health {
        proxy_pass http://api_backend;
        proxy_connect_timeout 5s;
        proxy_read_timeout 5s;
    }
}

Configuracao Prometheus

O Prometheus pode monitorar a disponibilidade via blackbox exporter:

yaml
scrape_configs:
  - job_name: 'procases-health'
    metrics_path: /probe
    params:
      module: [http_2xx]
    static_configs:
      - targets:
          - http://api:3000/health
          - http://api:3000/health/ready
          - http://api:3000/health/live
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox-exporter:9115

Documentacao OpenAPI

Os endpoints estao documentados com decorators Swagger:

typescript
@ApiTags('Health')         // Agrupa na tag "Health"
@ApiOperation({...})       // Descricao do endpoint
@ApiResponse({             // Schema de resposta
  status: 200,
  schema: {
    type: 'object',
    properties: {
      status: { type: 'string', example: 'ok' },
      // ...
    },
  },
})

A documentacao fica disponivel em /api/docs (Scalar UI) e /api/docs-json (OpenAPI JSON).


Monitoramento com Grafana

Dashboard sugerido para monitorar health checks:

PainelQueryDescricao
Uptimeprobe_success{job="procases-health"}1 = UP, 0 = DOWN
Latenciaprobe_duration_seconds{job="procases-health"}Tempo de resposta
Historicochanges(probe_success[1h])Mudancas de estado na ultima hora

Debugging

Testar manualmente

bash
# Health check geral
curl -s http://localhost:3000/health | jq

# Readiness
curl -s http://localhost:3000/health/ready | jq

# Liveness
curl -s http://localhost:3000/health/live | jq

Problemas Comuns

ProblemaCausaSolucao
404 em /healthController nao registrado no app.moduleVerificar imports no AppModule
401 em /health@Public() nao aplicadoAdicionar decorator @Public()
Health OK mas API falhaHealth nao verifica dependenciasImplementar verificacao de DB/Redis no readiness
Uptime sempre baixoProcesso reiniciando em loopVerificar logs de crash, memory leaks
Timeout no health checkProcesso sobrecarregadoVerificar CPU/memoria, event loop lag

Regras Importantes

  1. Todos os 3 endpoints sao publicos - sem autenticacao
  2. Nunca retornam erro na implementacao atual - sempre 200
  3. Nao verificam dependencias (banco, Redis) - apenas o processo Node.js
  4. O uptime e em segundos com fracionario (ex: 86432.159)
  5. O status do /health e "ok :D" com smiley face (intencional)
  6. Sao endpoints GET - sem body, sem query params
  7. Nao possuem rate limiting - sistemas de monitoramento chamam frequentemente
  8. Estao na tag "Health" do Swagger para organizacao na documentacao
  9. Usar /health/ready para load balancers e /health/live para restart policies
  10. Considerar adicionar verificacao de dependencias ao /health/ready em producao

Documentação Técnica - ProCases