# Сон и пробуждение

> Когда приложение засыпает, как просыпается на первый запрос и почему минуты сна не тарифицируются.

Раздел: Приложение
Источник: https://nodbox.ru/docs/apps/sleep/

---
Приложение засыпает, когда на его адрес не приходят запросы дольше выбранной паузы: экземпляров становится ноль, версия остаётся работающей, адрес остаётся тем же. Первый запрос будит приложение: посетитель ждёт, пока поднимется экземпляр, и получает обычный ответ, а минуты сна не тарифицируются.

Сон включён у веб-приложений по умолчанию, пауза по умолчанию - 15 минут. Воркеры не засыпают.

## Что значит «приложение спит»

Сон - состояние здорового приложения, а не сбой. Пока приложение спит:

- экземпляров ноль, ни один процесс не запущен
- версия остаётся работающей: её код, переменные и размер на месте, статус `active`, фаза `deployed`
- в панели статус «Спит», в API `status` равен `sleeping`, а `instances` равен `0`
- минуты не тарифицируются, об этом ниже
- приложение по-прежнему занимает место в лимитах проекта

Спящее приложение - это не остановленное. Остановку выбираешь ты, и после неё приложение не отвечает, пока его не запустят. Сон наступает сам и заканчивается первым запросом. Сравнение двух состояний - в конце страницы.

## Когда приложение засыпает

Приложение засыпает, когда его адрес молчит дольше паузы. Пауза и сам сон настраиваются двумя полями приложения:

| Поле API | Что значит | По умолчанию | Допустимые значения |
| --- | --- | --- | --- |
| `sleep_enabled` | засыпает ли приложение без запросов | `true` | `true` или `false` |
| `sleep_after_seconds` | сколько тишины ждать перед сном, в секундах | `900` | от 60 до 3 600 |

В панели пауза выбирается из четырёх значений: через 5 минут, через 15 минут, через 30 минут и через час. Другие значения от 60 секунд до часа можно задать по API.

Пауза называет минимальный срок. Перед ней платформа убеждается, что запросов нет, и это занимает около минуты, поэтому приложение засыпает позже названного срока. В замере при паузе 300 секунд приложение уснуло через 363 секунды после последнего запроса. Потому панель и пишет «заснёт не раньше этого срока».

Пауза оплачивается. Пока экземпляр жив, он тарифицируется, в том числе пока ждёт конца паузы. Если запросы приходят реже, чем раз в паузу плюс минуту, приложение успевает уснуть между ними. Если чаще, оно не засыпает вовсе. Если запросы приходят раз в 20 минут, а пауза 15, приложение бодрствует около 16 минут из каждых 20 и стоит почти как круглосуточное. Пауза короче сократит оплачиваемое время, но посетителю чаще придётся ждать пробуждения.

## Как приложение просыпается

Запрос к спящему приложению не теряется и не получает ошибку. Платформа держит запрос, пока поднимается экземпляр, и отдаёт обычный ответ. Посетитель видит паузу перед первым байтом, а не страницу с ошибкой.

Сколько длится пауза, зависит от приложения. В трёх замерах на тестовом приложении-приветствии от запроса до первого байта прошло 1,25, 1,7 и 1,8 секунды. Платформа считает подъём от создания экземпляра до его готовности, а в готовность входит запуск твоего кода. Если приложение при старте долго прогревается, эта длительность целиком ляжет на первого посетителя. Остальные запросы идут как обычно, пока приложение не уснёт снова.

Платформа записывает, сколько занял последний подъём экземпляра, и показывает это в двух местах:

- в панели на странице приложения, строка «Последний подъём экземпляра занял ~1,0 с»
- в API, в поле `cold_start` приложения: `ms` с длительностью и `at` со временем

Что важно знать про это число:

- Замер идёт с точностью до секунды, поэтому панель показывает десятые доли, а в `ms` лежит целое число тысяч.
- Замер не включает путь запроса по сети, поэтому `curl` покажет чуть больше. В замере 1,25 секунды у клиента платформа записала 1 секунду.
- Это последний подъём любого экземпляра, а не только пробуждение из сна: второй экземпляр, поднявшийся под нагрузкой, тоже обновит замер.
- Подъём при деплое новой версии не замеряется. У приложения, которое ни разу не просыпалось, поле пустое.

## Что приложение теряет во сне

При сне экземпляр останавливается, а при пробуждении запускается новый. Из этого следует:

- Память не сохраняется. Кэш в процессе, сессии в памяти и счётчики начинаются заново.
- Локальные файлы не сохраняются. Постоянного диска у приложения нет, данные хранятся в [базе](/docs/databases/postgres/). Подробнее - в разделе [Границы платформы](/docs/help/limitations/).
- Фоновые циклы и таймеры внутри веб-процесса не работают, пока экземпляра нет. Расписание в самом приложении не разбудит приложение.
- Код запускается заново при каждом пробуждении. Чем быстрее стартует приложение, тем короче ожидание посетителя.

Если приложению нужно помнить что-то между запросами, держи это в базе, а не в памяти процесса.

## Как сон выглядит в панели и в API

В панели сон видно в трёх местах:

- на странице приложения в заголовке стоит статус «Спит»
- на вкладке «Обзор» квадратик экземпляров подписан «Спит, экземпляров нет», а под ним строка «Засыпает не раньше чем через 15 мин без запросов и просыпается от первого обращения»
- на вкладке «События» остаются записи «Приложение уснуло: экземпляры остановлены» и «Приложение работает: экземпляр поднят и отвечает», у второй рядом длительность подъёма

События хранятся 30 дней, время в них московское. Письма о сне платформа не шлёт: сон - норма, а не повод для тревоги.

В API те же сведения лежат в ответе `GET /api/v1/applications/{id}`, для него хватает права токена «читать»:

| Поле | Что отдаёт |
| --- | --- |
| `status` | состояние приложения, у спящего `sleeping`, слова описаны в разделе [Состояния приложения](/docs/observability/states/) |
| `instances` | сколько экземпляров поднято, у спящего `0`, пусто, если платформа ещё не проверяла |
| `cold_start` | длительность и время последнего подъёма экземпляра |
| `sleep_enabled`, `sleep_after_seconds` | настройки сна, которые уедут со следующей версией |

Историю сна и пробуждений отдаёт `GET /api/v1/applications/{id}/timeline`: засыпание записано как `runtime_sleeping`, пробуждение как `runtime_running`.

Платформа узнаёт о состоянии приложения проверкой раз в минуту. Пока открыта страница приложения, панель просит платформу перепроверить состояние каждые 15 секунд, и пробуждение она показывает через несколько секунд: в двух замерах через 3,2 и 3,8 секунды после ответа приложения. Без такой просьбы статус отстаёт до минуты. То же касается API: ручка `POST /api/v1/applications/{id}/observe` с правом «читать» просит перепроверить состояние сейчас и сразу отвечает тем, что платформа знает, а свежее значение появляется через несколько секунд.

Из-за проверки раз в минуту время в событиях указано с точностью до минуты. Приложение, которое проснулось и снова уснуло между двумя проверками, в событиях может не отразиться.

## Как изменить паузу или выключить сон

В панели открой страницу приложения, вкладку «Настройки», карточку «Сон и масштаб». Переключатель «Засыпать без запросов» включает и выключает сон, список «Когда засыпать» выбирает паузу. Нажми «Сохранить» или поставь галку «Задеплоить после сохранения», тогда кнопка заказывает и новую версию.

По API те же настройки меняет `PATCH /api/v1/applications/{id}`:

```json
{
  "sleep_enabled": true,
  "sleep_after_seconds": 1800
}
```

Правка сна ничего не деплоит. Версия запоминает сон и масштаб в момент заказа, поэтому работающее приложение живёт со старыми настройками, пока не выйдет следующая версия. Выключил сон и не увидел эффекта - закажи [версию](/docs/deploy/versions/). `PATCH` требует два права токена: «деплоить» и «менять мощность». Подробнее - в разделе [Токены и права](/docs/automation/tokens/).

## Почему минуты сна не тарифицируются

Цена приложения зависит от того, работает ли экземпляр. Пока экземпляр есть, ты платишь за размер приложения, а когда платформа видит, что экземпляров нет, цена становится нулевой. Каждый переход записывается: цена сна - это ноль в истории цен приложения, а не пауза в счёте.

Из этого следует:

- Ноль начинается, когда исчез последний экземпляр, а не когда пропали запросы. Время паузы оплачивается, сон - нет.
- Цена меняется с точностью до минуты. Минута, в которую приложение уснуло или проснулось, оплачивается целиком.
- Нулевую цену дают сон, остановка и падение. Подробнее про счёт - в разделе [Тарификация](/docs/project/billing/).
- В панели плитка «Содержание в месяц» во сне подписана «Сейчас не тарифицируется».
- Прогноз «хватит на столько-то дней» и проверка баланса перед заказом считают спящее приложение платным: оно может проснуться в любую секунду.

Пример: размер Eco 512 МБ стоит 380 ₽ в месяц круглосуточной работы. Если приложение бодрствует 4 часа в сутки, а остальное время спит, за месяц оно стоит около 63 ₽: это 4 часа из 24 от цены 380 ₽, плюс минуты пауз перед сном. С выключенным сном то же приложение стоит 380 ₽. Размеры и цены - в разделе [Размеры приложения](/docs/apps/sizes/).

## Спящее приложение занимает место в проекте

Сон освобождает деньги, но не лимиты. Приложение занимает в лимитах проекта свой размер, умноженный на максимальное число экземпляров, и держит это место, пока существует, в том числе во сне и после остановки. Место нужно приложению, чтобы проснуться в любой момент. Освобождает его только удаление приложения. Лимиты и остаток описаны в разделе [Лимиты и квоты](/docs/project/limits/).

## Воркеры не спят

У воркера нет адреса, запросов к нему никто не шлёт и будить его некому. Поэтому один экземпляр воркера работает всегда, а тарифицируется он круглосуточно. В панели у воркера нет переключателя сна и паузы, а поля `sleep_enabled` и `sleep_after_seconds` в API принимаются, но игнорируются. Чем воркер отличается от веб-приложения, разбирает страница [Веб-приложения и воркеры](/docs/apps/types/).

## Как не дать приложению заснуть

Выключи сон: переключатель «Засыпать без запросов» или `sleep_enabled: false`. Тогда платформа держит минимум один экземпляр всегда. Отдельной настройки минимума экземпляров нет: выключенный сон и есть минимум в один экземпляр, включённый - минимум в ноль. Потолок задаёт поле `max_instances`, по умолчанию он равен 1, а под нагрузкой платформа добавляет экземпляры до него, как описано в разделе [Автомасштабирование](/docs/apps/scaling/).

Цена такого решения - полная цена размера за все минуты месяца. Выключенный сон нужен, когда:

- приложение должно отвечать без паузы пробуждения
- приложению нужна память процесса между запросами
- внутри приложения работает расписание или фоновый цикл
- внешний сервис шлёт вебхуки и не ждёт ответа дольше секунды

Если хватит паузы подлиннее, поставь час: это максимум, приложение уснёт не раньше чем через 60 минут тишины. Любой запрос обнуляет отсчёт, поэтому внешний монитор, который опрашивает адрес чаще паузы, тоже не даст приложению заснуть. Платить в этом случае придётся как за круглосуточную работу.

## Сон и остановка

| | Сон | Остановка |
| --- | --- | --- |
| Кто решает | платформа, по тишине | ты |
| Что с версией | остаётся работающей | заменена, статус «Отработала» |
| Как возвращается | первый запрос | запуск, он заказывает новую версию с образом прежней |
| Статус | «Спит», `sleeping` | «Остановлено», `stopped` |
| Цена | ноль | ноль |
| Место в лимитах | занято | занято |

Остановка и запуск описаны на странице [Остановка и удаление](/docs/apps/lifecycle/).

## Что дальше

- [Состояния приложения](/docs/observability/states/) - что значат «Работает», «Спит» и «Упало»
- [Автомасштабирование](/docs/apps/scaling/) - как платформа добавляет экземпляры под нагрузку
- [Тарификация](/docs/project/billing/) - как считаются деньги по минутам
- [Лимиты и квоты](/docs/project/limits/) - какое место занимает приложение в проекте
- [Остановка и удаление](/docs/apps/lifecycle/) - чем остановка отличается от сна
- [Лента событий](/docs/observability/events/) - засыпания и пробуждения в истории приложения
