Срок жизни SMS: когда настраивать TTL и прекращать доставку

1 мин
Время чтения

Срок жизни SMS, или TTL, определяет, как долго сообщение имеет смысл доставлять. Если телефон выключен или сеть недоступна, SMS может оставаться в обработке. Без разумного ограничения код входа приходит после истечения сессии, напоминание — после события, а акция — после завершения предложения.

TTL не ускоряет доставку и не гарантирует точность до секунды. Это верхняя граница полезности, после которой система должна прекратить попытки и зафиксировать просрочку. Настройка включает два уровня: срок задачи в вашей очереди и validity period на стороне SMS-шлюза или оператора.

Почему «доставить любой ценой» вредно

Устаревшее сообщение не просто бесполезно. Оно может запутать человека и запустить неправильное действие. Клиент вводит старый OTP, приезжает за уже выданным заказом или переходит по акции с закрытыми условиями.

Для каждой коммуникации задайте ответ на вопрос: «После какого момента это сообщение лучше не показывать вообще?» Этот момент и становится бизнес-дедлайном. Он зависит от сценария, а не от общего срока хранения у провайдера.

Два таймера

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

Оба уровня нужны. Только внешний validity period не остановит задачу, которая час пролежала в вашей очереди и была передана шлюзу уже устаревшей. Только внутренний TTL не ограничит дальнейшие попытки доставки после того, как провайдер принял сообщение.

В SMPP для этого существует поле validity_period; спецификация также выделяет финальное состояние EXPIRED, когда срок действительности закончился (SMPP v3.4). В HTTP API название и формат параметра зависят от провайдера.

Как выбрать срок

Начните с бизнес-процесса:

  • OTP — срок сессии плюс небольшой технический запас, но не часы;
  • подтверждение операции — пока действие можно безопасно подтвердить;
  • напоминание о записи — до начала или согласованной точки отмены;
  • статус заказа — пока статус остаётся актуальным;
  • срочное изменение — пока пользователь ещё может отреагировать;
  • рекламная кампания — до конца предложения и разрешённого окна отправки.

Не копируйте один TTL на все шаблоны. Даже два сервисных сообщения могут иметь разную полезность. Значение лучше хранить в реестре сценариев рядом с шаблоном, приоритетом и маршрутом.

Время события и время отправки

TTL считают от бизнес-события, а не от момента, когда воркер наконец взял задачу. Если заказ изменился в 10:00, а очередь обработала событие в 10:20, у сообщения уже истрачено двадцать минут срока.

Храните как минимум occurred_at, queued_at, send_before и фактическое submitted_at. Это позволяет понять, где появилась задержка. Отдельно полезно время приёма и финального статуса провайдера.

Все метки приводите к единой временной зоне или UTC, а отображение делайте локальным. Ошибка зоны способна продлить жизнь сообщения на часы.

Что делать с просроченной задачей

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

Автоматически генерировать новую SMS вместо просроченной опасно. Новая отправка должна соответствовать актуальному состоянию. Например, заказ мог уже перейти на следующий этап, и старый шаблон больше не подходит.

TTL и повторные запросы

Повторные запросы к SMS API прекращаются не только после заданного числа попыток, но и по общему дедлайну. Перед каждой попыткой система сравнивает текущее время с send_before и оценивает, останется ли сообщение полезным после ожидаемой задержки.

Backoff нельзя растягивать за срок сценария. Для короткого OTP несколько длинных повторов хуже одного быстрого отказа с понятной возможностью запросить новый код.

TTL и DLR

Статус EXPIRED означает, что доставка не завершилась в срок, но детализация зависит от маршрута. Его нужно отличать от постоянной ошибки номера и временной недоступности. Общий словарь статусов рассмотрен в статье про DLR SMS.

Ваше приложение может считать сообщение бизнес-просроченным раньше, чем придёт финальный DLR. Сохраните оба факта: «пользовательский срок закончился» и «провайдер сообщил финальное состояние». Не меняйте бизнес-решение обратно, если поздний статус пришёл после дедлайна.

Поведение при восстановлении после сбоя

После длительной аварии очередь содержит смесь актуальных и устаревших задач. Сначала отфильтруйте TTL, затем восстановите отправку с ограниченной скоростью и по приоритетам. Нельзя просто «дренировать всё»: именно так пользователи получают вчерашние уведомления после ремонта.

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

Метрики

Считайте отдельно:

  • просрочку до отправки в API;
  • финальный статус expired у провайдера;
  • задержку от события до submit;
  • долю доставки внутри бизнес-дедлайна;
  • возраст задач по сценарию;
  • число поздних DLR после бизнес-просрочки.

Общая доля доставленных может выглядеть высокой, хотя значимая часть сообщений приходит после полезного срока. Поэтому показатель «доставлено вовремя» важнее простого delivered для чувствительных сценариев.

Тестирование

Создайте задачу с коротким TTL, остановите воркер и дождитесь просрочки. После запуска задача должна получить статус отмены без вызова внешнего API. Затем передайте сообщение провайдеру с тестовым validity period и проверьте обработку EXPIRED.

Также измените системное время в тестовой среде или используйте управляемые часы, чтобы проверить границу срока, временные зоны и переход между датами. Не полагайтесь только на ожидание реальных минут в автотестах.

Опасность значения по умолчанию

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

То же относится к нулю и пустой строке: разные API могут трактовать их как «сразу истекло», «использовать default» или «без ограничения». Зафиксируйте точный формат из документации выбранного шлюза и покройте его интеграционным тестом.

Изменение события до отправки

Иногда сообщение ещё не просрочено по времени, но уже устарело по состоянию. Заказ успел перейти из «собран» в «выдан», запись отменена, платёж подтверждён. Перед отправкой критичных шаблонов полезно проверить текущую версию бизнес-объекта.

В задаче хранится версия события. Если состояние изменилось, старая задача отменяется или заменяется новой операцией с отдельным idempotency key. Это предотвращает последовательную доставку нескольких формально действующих, но противоречащих друг другу статусов.

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

Итог

TTL превращает «попытаться доставить» в управляемое обещание по времени. Для этого срок задаётся от бизнес-события, проверяется в собственной очереди, передаётся провайдеру и отражается в DLR. Устаревшие задачи фиксируются и отменяются, а не отправляются после аварии. Так SMS остаётся своевременным уведомлением, а не запоздалым источником путаницы.

Обновлено 28 августа, 2026
Подходит каждому
SMS-рассылка для любой сферы бизнеса
Узнайте как внедрить SMS-рассылку в ваш бизнес вместе с quicktel
Оставьте номер и вам перезвонит менеджер.