Skip to main content

Nomenclaturas de health check em projetos modernos | API | CSharp

  • Nomenclaturas de health check em projetos modernos | API | CSharp

Visão geral

Health check é um mecanismo usado para indicar se uma aplicação, serviço, container ou dependência está em condição adequada para operar.

Em projetos modernos, health check não significa apenas “a API respondeu 200”. Existem diferentes tipos de verificação, cada um com uma responsabilidade diferente:

NomePergunta que respondeQuem costuma usar
healthO serviço está saudável de forma geral?Monitoramento, dashboards, humanos
live / livenessO processo ainda está vivo ou travou?Kubernetes, orchestrator
ready / readinessA aplicação está pronta para receber tráfego?Load balancer, Kubernetes, gateway
startupA aplicação terminou a inicialização?Kubernetes
deep healthAs dependências críticas estão funcionando?Monitoramento, troubleshooting
shallow healthA aplicação responde minimamente?Orchestrator, balanceador
dependency healthBanco, Redis, RabbitMQ, APIs externas estão acessíveis?Observabilidade
synthetic checkUm fluxo real do sistema funciona de ponta a ponta?Monitoramento externo
heartbeatO componente ainda envia sinais de vida?Workers, jobs, consumidores
pingA aplicação responde de forma simples?Testes básicos, load balancer

Health check

health é o nome mais genérico.

Normalmente representa um endpoint geral, como:

GET /health

Ele pode ser simples ou composto:

{
"status": "Healthy",
"checks": {
"database": "Healthy",
"redis": "Healthy",
"rabbitmq": "Degraded"
}
}

No ASP.NET Core, health checks são expostos como endpoints HTTP e podem ser usados por orquestradores, balanceadores de carga e ferramentas de monitoramento para avaliar o estado da aplicação e das dependências. (Microsoft Learn)

Para que serve

  • Verificar o estado geral da aplicação
  • Exibir informações para observabilidade
  • Apoiar dashboards como Grafana, Datadog, New Relic, Prometheus ou Uptime Kuma
  • Validar dependências principais

Quando usar

Use /health como endpoint geral para humanos, dashboards e ferramentas de monitoramento.


Liveness check

liveness responde à pergunta:

O processo ainda está vivo ou ficou preso em um estado irrecuperável?

Exemplo comum:

GET /health/live

No Kubernetes, se uma liveness probe falha, o container pode ser morto e reiniciado. A documentação mostra que, quando o comando ou endpoint configurado retorna falha, o kubelet considera o container não saudável e reinicia o container. (Kubernetes)

Para que serve

  • Detectar deadlock
  • Detectar processo travado
  • Detectar loop infinito
  • Detectar aplicação sem capacidade mínima de responder
  • Forçar restart automático pelo orquestrador

O que não deve verificar

Evite colocar banco de dados, Redis, RabbitMQ ou API externa no liveness.

Se o banco cair e o liveness depender dele, o orquestrador pode reiniciar todos os containers da aplicação sem resolver o problema real.

Exemplo correto

GET /health/live

Resposta:

{
"status": "Healthy"
}

Regra prática

liveness deve responder:

Minha aplicação está viva o suficiente para continuar rodando?

Não deve responder:

Todas as minhas dependências estão funcionando?


Readiness check

readiness responde à pergunta:

A aplicação está pronta para receber tráfego agora?

Exemplo comum:

GET /health/ready

No Kubernetes, readiness probes servem para detectar quando a aplicação não deve receber tráfego. Um pod que não está pronto não recebe tráfego via Kubernetes Services. (Kubernetes)

Para que serve

  • Remover uma instância do balanceamento
  • Impedir tráfego durante startup
  • Impedir tráfego quando dependências críticas estão indisponíveis
  • Ajudar em deploy rolling update
  • Evitar que uma instância receba requisições antes da hora

O que pode verificar

  • Banco de dados
  • Redis
  • RabbitMQ
  • Configurações obrigatórias carregadas
  • Migrações aplicadas
  • Cache inicial carregado
  • Conexão com serviços internos críticos

Exemplo

{
"status": "Unhealthy",
"checks": {
"database": "Healthy",
"rabbitmq": "Unhealthy"
}
}

Nesse caso, a aplicação pode estar viva, mas não pronta.

Regra prática

readiness deve responder:

Posso receber tráfego de produção neste momento?


Startup check

startup responde à pergunta:

A aplicação já terminou sua inicialização?

Exemplo comum:

GET /health/startup

O Kubernetes usa startup probes para aplicações que demoram mais para iniciar. Depois que a startup probe passa, a liveness probe assume o papel de detectar travamentos. (Kubernetes)

Para que serve

  • Evitar que aplicações lentas sejam reiniciadas antes de terminar o boot
  • Separar tempo de inicialização de falha real
  • Proteger aplicações que carregam cache, modelos, configurações ou conexões demoradas
  • Evitar falsos positivos no liveness

Quando usar

Use quando a aplicação demora para subir, por exemplo:

  • API que carrega cache grande
  • Serviço que precisa aquecer conexão
  • Aplicação que valida configuração no boot
  • Serviço que executa migração controlada
  • Aplicação com inicialização pesada

Regra prática

startup deve responder:

O processo terminou a fase de boot?


Deep health

deep health é uma verificação mais profunda.

Exemplo:

GET /health/deep

Ela valida não apenas se a aplicação responde, mas também se as dependências importantes estão operacionais.

Para que serve

  • Diagnóstico operacional
  • Troubleshooting
  • Painéis internos
  • Verificação de dependências críticas
  • Análise de degradação

Pode validar

  • PostgreSQL
  • SQL Server
  • MongoDB
  • Redis
  • RabbitMQ
  • Kafka
  • APIs internas
  • Storage
  • Permissões
  • Filas
  • Backplane
  • Configurações obrigatórias

Cuidado

Não use deep health como liveness.

Se uma dependência externa cair, isso não significa necessariamente que o processo da aplicação precisa ser reiniciado.


Shallow health

shallow health é uma verificação superficial.

Exemplo:

GET /health/shallow

Ela valida apenas se a aplicação consegue responder.

Para que serve

  • Verificação rápida
  • Baixo custo
  • Uso por balanceadores
  • Uso por orquestradores
  • Evitar checks pesados em alta frequência

Exemplo de resposta

{
"status": "Healthy"
}

Diferença para deep health

TipoVerifica dependências?CustoUso recomendado
shallowNãoBaixoLiveness, balanceador simples
deepSimMédio/altoMonitoramento e diagnóstico

Dependency health

dependency health verifica uma dependência específica.

Exemplos:

GET /health/database
GET /health/redis
GET /health/rabbitmq
GET /health/signalr-backplane

Para que serve

  • Isolar falhas
  • Saber exatamente qual dependência está indisponível
  • Ajudar troubleshooting
  • Separar falha da aplicação de falha de infraestrutura

Exemplo

{
"name": "postgres",
"status": "Healthy",
"latencyMs": 12
}

Boa prática

Evite expor detalhes sensíveis publicamente.

Esses endpoints devem ficar internos ou protegidos.


Ping

ping é a verificação mais simples possível.

Exemplo:

GET /ping

Resposta:

pong

Para que serve

  • Testar se a aplicação responde
  • Validar rota no gateway
  • Validar DNS
  • Validar roteamento
  • Validar se o processo HTTP está aceitando conexão

Limitação

ping não prova que a aplicação está funcional.

Ele apenas indica que existe uma resposta básica.


Heartbeat

heartbeat é um sinal periódico enviado por um componente para dizer:

Ainda estou vivo.

Muito usado em:

  • Workers
  • Consumers
  • Serviços background
  • Clientes conectados
  • Agentes locais
  • Sistemas distribuídos
  • SignalR, MQTT, WebSocket ou processos long-running

Exemplo

{
"service": "worker-publicacao-retorno",
"instanceId": "worker-01",
"status": "alive",
"timestamp": "2026-05-19T17:20:00Z"
}

Para que serve

  • Saber se um worker ainda está ativo
  • Detectar consumidores parados
  • Detectar cliente desconectado
  • Atualizar presença
  • Monitorar agentes remotos

Diferença para health check

ItemHealth checkHeartbeat
ModeloAlguém perguntaO componente avisa
DireçãoPullPush
ExemploPrometheus consulta /healthWorker publica “estou vivo”
UsoAPIs e serviçosWorkers, consumidores e agentes

Synthetic check

synthetic check é uma verificação que simula um fluxo real.

Exemplo:

  • Fazer login
  • Criar pedido fake
  • Enviar comando de teste
  • Consultar status
  • Validar resposta
  • Remover dados de teste

Para que serve

  • Validar experiência real
  • Detectar falhas que health check simples não detecta
  • Monitorar jornada crítica
  • Verificar integração de ponta a ponta

Exemplo

1. Envia comando de teste
2. Recebe requestId
3. Aguarda retorno
4. Confirma que o resultado chegou na fila

Cuidado

Synthetic checks devem ser controlados para não gerar dados inválidos, custo excessivo ou efeitos colaterais.


Status comuns

Em projetos modernos, os statuses mais comuns são:

StatusSignificado
HealthyTudo certo
UnhealthyFalha crítica
DegradedFunciona parcialmente
UnknownEstado não determinado
StartingInicializando
NotReadyVivo, mas não pronto para tráfego
TimeoutVerificação excedeu o tempo limite

No Docker, o HEALTHCHECK usa código de saída para indicar saúde do container: 0 significa saudável, 1 significa não saudável, e 2 é reservado. (Docker Documentation)


Nomenclatura recomendada para APIs HTTP

Uma estrutura clara seria:

GET /health
GET /health/live
GET /health/ready
GET /health/startup
GET /health/deep
GET /health/dependencies
GET /ping

Sugestão prática

EndpointUso
/pingTeste simples de conectividade
/health/liveLiveness probe
/health/readyReadiness probe
/health/startupStartup probe
/healthEstado geral
/health/deepDiagnóstico interno completo
/health/dependenciesEstado das dependências

Diferença entre health, live e ready

EndpointVerificaPode reiniciar container?Pode remover do tráfego?Deve verificar banco?
/health/liveProcesso vivoSimNão necessariamenteNão
/health/readyPronto para tráfegoNãoSimSim, se for crítico
/health/startupBoot finalizadoSim, se nunca subirSimDepende
/healthEstado geralNão diretamenteNão diretamentePode
/health/deepDiagnóstico completoNãoNão diretamenteSim

Exemplo em .NET

using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Diagnostics.HealthChecks;

var builder = WebApplication.CreateBuilder(args);

builder.Services
.AddHealthChecks()
.AddCheck("self", () => HealthCheckResult.Healthy(), tags: ["live"])
.AddCheck("startup", () => HealthCheckResult.Healthy(), tags: ["startup"])
.AddNpgSql(
builder.Configuration.GetConnectionString("Postgres")!,
name: "postgres",
tags: ["ready", "deep", "dependencies"]);

var app = builder.Build();

app.MapGet("/ping", () => Results.Ok("pong"));

app.MapHealthChecks("/health");

app.MapHealthChecks("/health/live", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("live")
});

app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("ready")
});

app.MapHealthChecks("/health/startup", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("startup")
});

app.MapHealthChecks("/health/deep", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("deep")
});

app.Run();

Exemplo com Kubernetes

apiVersion: apps/v1
kind: Deployment
metadata:
name: minha-api
spec:
replicas: 3
selector:
matchLabels:
app: minha-api
template:
metadata:
labels:
app: minha-api
spec:
containers:
- name: minha-api
image: minha-api:latest
ports:
- containerPort: 8080

startupProbe:
httpGet:
path: /health/startup
port: 8080
failureThreshold: 30
periodSeconds: 10

livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
failureThreshold: 3

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

O Kubernetes permite probes HTTP, TCP e gRPC. A própria documentação mostra liveness por HTTP, TCP e gRPC, e o gRPC ficou estável para probes a partir do Kubernetes v1.27. (Kubernetes)


Exemplo com Docker Compose

services:
minha-api:
image: minha-api:latest
ports:
- "8080:8080"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health/live"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s

No Docker Compose, healthcheck declara o comando usado para determinar se o container está saudável, podendo configurar interval, timeout, retries, start_period e start_interval. (Docker Documentation)


Exemplo com gRPC

Em serviços gRPC, existe um protocolo padrão de health checking. O servidor expõe um serviço de health check e o cliente pode usar esse estado para evitar enviar chamadas para backends não saudáveis. (gRPC)

Estados comuns no gRPC health checking:

StatusSignificado
SERVINGServiço disponível
NOT_SERVINGServiço indisponível
UNKNOWNEstado desconhecido

Exemplo conceitual:

grpc.health.v1.Health/Check

Resposta:

{
"status": "SERVING"
}

Como escolher o nome correto

CenárioNome recomendado
Quero saber se a API responde/ping
Quero saber se o processo travou/health/live
Quero saber se pode receber tráfego/health/ready
Quero proteger aplicação lenta no boot/health/startup
Quero ver estado geral/health
Quero validar dependências críticas/health/deep
Quero validar banco isoladamente/health/database
Quero validar Redis isoladamente/health/redis
Quero validar fluxo real de negóciosynthetic check
Quero saber se worker está vivoheartbeat

Boas práticas

  • Não coloque dependências externas no liveness.
  • Use readiness para tirar a instância do tráfego sem reiniciar.
  • Use startup para aplicações que demoram para inicializar.
  • Use deep health apenas para diagnóstico e monitoramento interno.
  • Não exponha detalhes de banco, host, string de conexão ou exceções em endpoints públicos.
  • Configure timeout curto para cada dependência.
  • Evite health checks pesados em alta frequência.
  • Separe status operacional de status de negócio.
  • Retorne HTTP 200 para saudável e 503 para indisponível.
  • Em APIs públicas, exponha apenas o mínimo necessário.
  • Em dashboards internos, exponha detalhes por dependência.

Exemplo de estratégia recomendada

Para uma API moderna em .NET atrás de APISIX, Nginx, Kubernetes, Docker Swarm ou Load Balancer:

EndpointPúblico?Usado porVerifica
/pingSimGateway / teste manualResposta simples
/health/liveInternoOrquestradorProcesso vivo
/health/readyInternoLoad balancer / gatewayPronto para tráfego
/health/startupInternoOrquestradorInicialização
/healthInternoMonitoramentoEstado geral
/health/deepNãoObservabilidade internaDependências
/metricsNãoPrometheusMétricas

Exemplo de erro comum

Errado

app.MapHealthChecks("/health/live", new HealthCheckOptions
{
Predicate = _ => true
});

Esse exemplo faz o liveness validar tudo, incluindo banco, Redis, RabbitMQ e APIs externas.

Se o banco cair, o container pode ser reiniciado sem necessidade.

Melhor

app.MapHealthChecks("/health/live", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("live")
});

app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("ready")
});

Assim:

  • /health/live valida se o processo está vivo
  • /health/ready valida se a aplicação pode receber tráfego

Resumo rápido

NomeServe para
pingVerificar resposta mínima
healthEstado geral
livenessSaber se deve reiniciar
readinessSaber se deve receber tráfego
startupProteger inicialização lenta
deep healthDiagnóstico completo
shallow healthVerificação leve
dependency healthVerificar dependência específica
heartbeatSinal periódico de vida
synthetic checkSimular fluxo real