Проверяем endpoint:
curl -I https://app.example.ru/health
Получаем:
HTTP/1.1 200 OK
Первый вывод:
приложение работает.
Но HTTP 200 подтверждает только то, что конкретный HTTP-запрос завершился успешным ответом.
Это ещё не означает, что вся система исправна.
HTTP 200 ≠ приложение полностью работоспособно
Что на самом деле доказывает 200 OK
Если запрос:
GET /health
вернул:
200 OK
мы знаем:
этот endpoint ответил успешно в этот момент времени.
Это полезный факт.
Но дальше начинается главный вопрос:
что именно проверяет этот endpoint?
Вариант 1. Health endpoint проверяет только процесс
Например, приложение отвечает:
200 OK
пока его основной процесс жив.
Но при этом база данных недоступна:
application → alive database → timeout
Тогда:
/health → 200
а пользовательский запрос может завершаться:
500 Internal Server Error
То есть:
process alive
≠
application usableВариант 2. Проверяется приложение, но не внешние зависимости
Допустим:
application → OK database → OK
но система зависит от внешнего API:
application
↓
payment APIЕсли payment API недоступен, основной health check всё ещё может возвращать:
200 OK
При этом конкретная бизнес-функция уже не работает.
Вариант 3. HTTP отвечает, но аутентификация сломана
Например:
GET / → 200 OK
но:
login → failed
или:
OIDC redirect → error
Тогда инфраструктурно приложение отвечает.
Функционально пользователь войти не может.
Для IAM-зависимых систем это критично.
Вариант 4. Ответ правильный, но данные — нет
Можно получить:
HTTP 200
и одновременно неправильный результат.
Например API возвращает:
{
"status": "ok",
"orders": []
}Хотя заказы в системе точно есть.
С точки зрения HTTP всё успешно.
С точки зрения бизнес-логики — нет.
Поэтому:
200 OK
≠
данные корректныВариант 5. Endpoint работает, а пользовательский сценарий — нет
Представим путь:
user ↓ frontend ↓ API ↓ database ↓ external service
Health check проверяет только:
API process → OK
А реальный пользовательский сценарий требует:
login ↓ request ↓ database ↓ external API ↓ response
Если один из этих шагов не работает, приложение для пользователя неисправно, даже если /health зелёный.
Вариант 6. Сервис отвечает, но деградировал
Допустим:
HTTP 200
но время ответа:
12 секунд
Формально запрос успешен.
Практически пользователь считает систему неработоспособной.
Поэтому:
response successful
≠
response acceptableВ мониторинге важно учитывать не только код ответа, но и:
- время отклика;
- error rate;
- saturation;
- зависимые сервисы;
- пользовательский сценарий.
Health check должен отвечать на конкретный вопрос
Есть принципиальная разница между:
процесс жив?
и:
экземпляр готов принимать трафик?
и:
пользовательский сценарий работает?
Это три разных уровня проверки.
Например:
liveness ↓ процесс не завис и не умер
readiness ↓ сервис готов обслуживать запросы
synthetic transaction ↓ критичный пользовательский сценарий реально выполняется
Чем ниже мы идём, тем сильнее доказательство.
Почему слишком простой /health опасен
Представим:
/health → 200
всегда, пока процесс запущен.
Monitoring показывает:
UP
Load balancer продолжает отправлять трафик.
Но база уже недоступна.
health = OK
↓
traffic continues
↓
users receive errorsВ таком случае health check не просто бесполезен.
Он может даже маскировать проблему.
Но слишком «глубокий» health check тоже может быть проблемой
Если endpoint на каждый запрос проверяет:
— базу;
— LDAP;
— внешний API;
— SMTP;
— storage;
— ещё пять зависимостей,
то отказ одной некритичной зависимости может сделать весь экземпляр:
UNHEALTHY
и load balancer исключит его из работы.
Хотя основная функция системы могла продолжать работать.
Поэтому health check должен соответствовать реальной цели проверки.
Что лучше проверять
Для инфраструктуры полезно разделять уровни.
Например:
- Process health
- Readiness
- Dependency health
- End-to-end user flow
Тогда каждый сигнал отвечает на свой вопрос.