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
| Camada | Arquivo | Responsabilidade |
|---|---|---|
| Presentation | src/presentation/controllers/health.controller.ts | Controller com 3 endpoints |
| Config | src/app.module.ts | Registro do controller |
O controller e marcado com @Public() no nivel de classe, tornando todos os seus endpoints acessiveis sem autenticacao.
Controller Completo
@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):
{
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:
{
"status": "ok :D",
"timestamp": "2025-06-15T14:30:00.000Z",
"uptime": 86432.159
}Campos:
| Campo | Tipo | Descricao |
|---|---|---|
status | string | Sempre "ok :D" se o processo esta rodando |
timestamp | string | Data/hora atual do servidor em ISO 8601 |
uptime | number | Tempo 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):
{
status: "ready"
}Exemplo de response:
{
"status": "ready"
}Uso em Kubernetes:
readinessProbe:
httpGet:
path: /health/ready
port: 3000
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3Semantica: 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:
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):
{
status: "alive"
}Exemplo de response:
{
"status": "alive"
}Uso em Kubernetes:
livenessProbe:
httpGet:
path: /health/live
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3Semantica: 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
| Endpoint | Proposito | Quando Falhar | Acao do Orchestrator |
|---|---|---|---|
/health | Verificacao geral | Processo crashou | Alertar operadores |
/health/ready | Pronto para trafico | Dependencias indisponiveis | Remover do pool |
/health/live | Processo vivo | Deadlock/hang | Reiniciar 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 poolFluxo 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 desnecessariaDecorator @Public()
Todos os endpoints de health sao publicos:
@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:
- Health checks sao chamados por sistemas automatizados (Kubernetes, Prometheus)
- Esses sistemas nao possuem sessao ou cookies
- Os endpoints nao expoe dados sensiveis
Configuracao Docker Compose
services:
api:
image: procases-api
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sO start_period permite que a aplicacao tenha tempo de inicializar antes de comecar a verificar health.
Configuracao Kubernetes
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: 30startupProbe: 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:
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:
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:9115Documentacao OpenAPI
Os endpoints estao documentados com decorators Swagger:
@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:
| Painel | Query | Descricao |
|---|---|---|
| Uptime | probe_success{job="procases-health"} | 1 = UP, 0 = DOWN |
| Latencia | probe_duration_seconds{job="procases-health"} | Tempo de resposta |
| Historico | changes(probe_success[1h]) | Mudancas de estado na ultima hora |
Debugging
Testar manualmente
# 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 | jqProblemas Comuns
| Problema | Causa | Solucao |
|---|---|---|
| 404 em /health | Controller nao registrado no app.module | Verificar imports no AppModule |
| 401 em /health | @Public() nao aplicado | Adicionar decorator @Public() |
| Health OK mas API falha | Health nao verifica dependencias | Implementar verificacao de DB/Redis no readiness |
| Uptime sempre baixo | Processo reiniciando em loop | Verificar logs de crash, memory leaks |
| Timeout no health check | Processo sobrecarregado | Verificar CPU/memoria, event loop lag |
Regras Importantes
- Todos os 3 endpoints sao publicos - sem autenticacao
- Nunca retornam erro na implementacao atual - sempre 200
- Nao verificam dependencias (banco, Redis) - apenas o processo Node.js
- O uptime e em segundos com fracionario (ex: 86432.159)
- O status do /health e
"ok :D"com smiley face (intencional) - Sao endpoints GET - sem body, sem query params
- Nao possuem rate limiting - sistemas de monitoramento chamam frequentemente
- Estao na tag "Health" do Swagger para organizacao na documentacao
- Usar /health/ready para load balancers e /health/live para restart policies
- Considerar adicionar verificacao de dependencias ao /health/ready em producao
