MAATRIX / Блог / Ресторан: интернет пропал в пятницу вечером — почему касса и стоп-лист должны быть локальными

Ресторан: интернет пропал в пятницу вечером — почему касса и стоп-лист должны быть локальными

MAATRIX

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

Пятница, 20:00: что на самом деле происходит при обрыве связи

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

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

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

Почему это ломается именно в пиковый час, а не когда удобно

Тут работает не мистика, а обычная перегрузка сети. Вечером в пятницу одновременно растёт нагрузка сразу с нескольких сторон: жители района массово выходят в сеть дома, торговые центры и заведения рядом гоняют трафик через тот же узел провайдера, а гостевой Wi-Fi самого ресторана раздаёт интернет десяткам смартфонов посетителей на том же канале, что и касса. Оборудование провайдера в узловой точке перегружается или уходит в защитный режим — и первым падает не голосовой звонок, а именно облачный API, чувствительный к задержкам и потере пакетов.

Кассовая система, построенная как «тонкий клиент», обращающийся в облако на каждое действие, спроектирована в расчёте на стабильную связь и плохо переносит короткие обрывы на 10-15 секунд, которые для человека выглядят как «интернет мигнул», а для системы — как полный отказ транзакции. Провайдеры кассового ПО в маркетинге часто говорят про доступность сервиса «почти всегда» — но это доступность их дата-центра, а не гарантия связи именно между рестораном и интернетом в конкретный вечер. Похожая путаница разбиралась и в контексте мифа про 99,9% аптайм: даже если облачный сервис работает безупречно, ваш локальный канал связи — отдельное и куда менее надёжное звено в цепочке.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Что обязано работать локально, а что можно смело оставить в облаке

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

Должно быть локальноМожно смело держать в облаке
Открытие смены и вход кассираСводная аналитика по продажам за период
Пробитие чека и печатьПрограмма лояльности и бонусные баллы
Стоп-лист и остатки на кухнеИнтеграция с агрегаторами доставки
Карта зала и статус столовЭкспорт в бухгалтерию и налоговая отчётность
Локальная печать на кухонный принтерОтчёты для владельца по нескольким точкам

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

Архитектура: локальный сервер в подсобке плюс облако для того, что не горит

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

Минимальный набор сервисов на локальном сервере:

services:
  db:
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_DB: pos
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    volumes:
      - pos_data:/var/lib/postgresql/data
    secrets: [db_password]

  pos_backend:
    build: ./pos
    restart: unless-stopped
    depends_on: [db]
    ports: ["8080:8080"]   # доступен только внутри локальной сети
    env_file: .env

  sync_worker:
    build: ./sync
    restart: unless-stopped
    depends_on: [db]
    environment:
      CLOUD_ENDPOINT: "https://backoffice.example-restaurant.ru"

volumes: { pos_data: }
secrets: { db_password: { file: ./secrets/db_password.txt } }

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

Резервный источник питания (ИБП) на сервере и сетевом оборудовании — отдельный обязательный пункт: скачок напряжения или короткое отключение света бьёт по тому же месту, что и обрыв интернета.

Стоп-лист и открытие смены: почему это тоже про локальность, а не только чеки

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

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

Синхронизация с облаком: как не потерять данные, когда связь вернётся

Локальный сервер копит операции, пока связи нет, и синхронизирует их с облачным узлом, когда канал восстановлен — это классический паттерн очереди с отложенной доставкой (outbox). Практическая реализация простая: каждая транзакция на локальном сервере получает уникальный идентификатор и метку времени сразу при создании, а фоновый процесс (sync_worker в примере выше) периодически пытается отправить накопившиеся записи в облако.

# псевдологика воркера синхронизации, раз в 30 секунд
while true; do
  for tx in $(get_unsynced_transactions); do
    if push_to_cloud "$tx"; then
      mark_synced "$tx"
    fi
  done
  sleep 30
done

Важно, чтобы отправка была идемпотентной — то есть повторная отправка уже доставленной транзакции не создавала дубль на облачной стороне. Это решается тем же уникальным идентификатором: облачный сервер при получении записи с уже известным ID просто подтверждает приём, не записывая её повторно. Конфликтов по данным о продажах здесь почти не бывает — они создаются один раз и не редактируются задним числом, а вот справочники (меню, цены, стоп-лист) стоит синхронизировать в одну сторону: изменения на кассе — источник истины для операционных данных, изменения в облаке (например, обновление меню из центрального офиса сети) — применяются на локальный сервер при следующем сеансе связи.

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

С чего начать перенос кассы на локальный сервер

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

  1. Проверьте архитектуру текущей кассы. Уточните у провайдера, работает ли касса в offline-режиме хотя бы частично (кеширование чеков локально с последующей отправкой) или полностью останавливается без связи — это определяет, достаточно ли донастроить существующее решение или нужна замена.
  2. Поставьте локальный сервер. Компактный мини-ПК с Linux, установленный в подсобке или серверном шкафу заведения — не требует дорогого железа, задача некрупная по нагрузке (десятки-сотни транзакций в смену для одной точки).
  3. Разверните POS-бэкенд и базу данных локально. Готовое open-source решение под ресторанный учёт или самописный бэкенд под конкретное меню — в любом случае, обе части (приложение и база) должны физически жить в здании ресторана.
  4. Переведите стоп-лист на тот же сервер. Не оставляйте его в старом облачном приложении — иначе локальная касса и актуальность меню разойдутся между собой в первый же вечер без связи.
  5. Настройте синхронизацию с облачным узлом. Арендованный сервер принимает данные, когда связь есть, и служит центром для отчётности, резервных копий и, при сети из нескольких точек, — сводной аналитики по всем заведениям сразу.
  6. Добавьте ИБП и проверьте резервный канал терминала. Питание и оплата картой — два дополнительных звена, которые стоит закрыть отдельно от самого факта наличия локального сервера.
  7. Прогоните тест «выключаем интернет специально». Лучше выключить роутер намеренно в спокойный вторник днём и проверить, что касса, стоп-лист и печать чеков продолжают работать, чем узнать о проблеме в пятницу в 20:00 на глазах у полного зала.

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

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

А если сломается сам локальный сервер, а не интернет?

Это отдельный риск, который закрывается иначе — резервным диском или вторым недорогим мини-ПК как холодной заменой, плюс регулярными бэкапами базы данных на внешний накопитель или в облако. Локальный сервер снимает зависимость от интернета, но не отменяет обычные требования к резервному копированию.

Нужно ли теперь два разных интернет-провайдера?

Это отдельная и полезная мера, но не обязательное условие для решения именно задачи с кассой — локальный сервер и без резервного канала связи держит зал рабочим, просто без синхронизации с облаком до восстановления связи. Второй провайдер или 4G-модем как резерв — следующий логичный шаг для полной отказоустойчивости.

Что делать с оплатой картой, если интернета совсем нет?

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

Сколько стоит такой локальный сервер?

Ресурсов нужно немного: для одной точки хватает недорогого мини-ПК с 4-8 ГБ RAM и небольшим SSD — нагрузка кассы и стоп-листа для одного заведения укладывается в десятки-сотни записей за смену. Основные затраты — не в железе, а в разовой настройке приложения под конкретное меню.

Можно ли обойтись вообще без облачной части?

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

Обсудить статью, задать вопрос или начать новую тему

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

Перейти в сообщество →