
Заказчик: Крупный спортивный объект — стадион «Крылья Советов» (около 45 000 мест), где в пиковые часы необходимо контролировать доступ десятков тысяч болельщиков, включая VIP-зоны, и отслеживать вход/выход в режиме реального времени.
Задача: Разработать облачную платформу управления мероприятиями и билетами, которая работает как со стационарными СКУД, так и на площадках без собственной инфраструктуры — через мобильные устройства. Поддержка офлайн-режима, интеграция с несколькими билетными системами, аналитика потоков посетителей.
Проблемы: Легаси-системы не контролировали, кто и куда заходит, — поэтому люди проходили по копиям билетов, в том числе в VIP-зоны. Отследить вход/выход и загрузку секторов было невозможно.
Что сделали: За 4 месяца команда АЙТИФОКС сделала облачную систему контроля доступа. Сервер — на Python, приложение — на Flutter (работает и на телефоне, и в браузере). Сначала выпустили MVP, протестировали на реальной нагрузке и нашли узкие места: при 45 000 билетов начали зависать устройства Xiaomi, сервер не справлялся с запросами. Перевели хранилище на SQLite + Drift, ускорили сервер.
В тестах система обработала 50 000 билетов и 224 852 прохода за один прогон. Это не «маленький объём», а нагрузка с запасом: 50 000 билетов — больше реальной вместимости стадиона (45 000), а 224 852 прохода — больше, чем даёт один матч (около 90 000 проходов на 45 000 зрителей). Подтверждённый порог — 200 RPS на тяжёлых операциях, это около 40 проходов/с. Для пикового сценария целевой показатель — 140 проходов/с (8 400 проходов/мин). Арифметически при 5 запросах на один проход это 700 RPS, но мы не выдаём это за подтверждённый боевой результат, пока нет отдельного нагрузочного теста. В лёгких тестах фиксировались 350–400 RPS, но как гарантированный запас мы их не закладываем.
Итог: Система прошла тестовый прогон на реальном матче. Подтверждённая скорость — около 40 проходов/с на тяжёлых операциях; для пикового запаса ориентир — 140 проходов/с.
Почему заказчик решил автоматизировать контроль доступа
Стадион в день матча, десятки тысяч болельщиков подходят ко входам. Контролёры вручную проверяют билеты, кто-то пытается пройти по копии, кто-то не туда. VIP-зоны — отдельная головная боль: туда периодически набиваются люди, которым там быть не положено, а если человек зашёл и вышел — никто не знает, вернулся он или нет.
Старая система была медленной и не давала никакой аналитики. Заказчику нужно было не просто «пускать по билетам», а управлять потоками: понимать, кто зашёл, куда зашёл, вышел ли, сколько людей в каждом секторе. И делать это в реальном времени — даже на площадках, где нет стационарных турникетов.
Идея: единая облачная платформа, которая работает и с существующей инфраструктурой (стационарные СКУД), и автономно — через мобильные устройства контролёров.
Задача и в чём была главная сложность
Самое трудное — не написать систему контроля доступа, а заставить её работать в реальных условиях стадиона: без интернета, на слабых устройствах, при большом потоке людей.
Первая сложность — объём данных. На небольших площадках система работала нормально. Но когда билетов в базе стало 45 000 — столько продаётся на один матч, — начались проблемы с двух сторон.
На клиенте: на устройствах Xiaomi начались зависания интерфейса — конкретно при открытии клавиатуры. Контролёр нажимает на поле ввода, а интерфейс не отвечает секунду-две. На других Android-смартфонах и на iPhone такого не было — там всё работало нормально.
На сервере: бэкенд не справлялся с объёмом запросов. Мы использовали SQLAlchemy — удобный инструмент для работы с базой данных, но он создавал лишнюю нагрузку. Запросы выполнялись медленнее, чем могли бы.
Вторая сложность — офлайн-режим. Стадионы — это места, где интернет может «упасть» в самый неподходящий момент. Система должна работать без сети: сканировать билеты, регистрировать проходы, а потом синхронизироваться. При этом объём данных немаленький: в тестах мы загружали на клиент до 50 000 билетов — это тестовая нагрузка с запасом.
Отдельно мы продумали более жёсткий сценарий: большой стадион и полное отсутствие интернета. Архитектура позволяет работать без сети — данные загружаются на устройство заранее, проходы фиксируются локально, синхронизация идёт при появлении связи. Офлайн-режим протестирован отдельно: система корректно сканирует билеты и регистрирует проходы без сети, а при восстановлении связи синхронизируется с сервером.
Третья сложность — организационная. Первый тестовый матч стал проверкой системы в реальных условиях. Полноценный прогон на большом потоке случился позже — так обычно и бывает, когда технология встречается с живыми процессами площадки.
Как проходит билет: путь от сканирования до прохода
Чтобы было понятно, что такое «тяжёлые» и «лёгкие» операции, вот весь путь билета:
1. Сканирование. Контролёр считывает QR-код или штрих-код с телефона болельщика или с ТСД.
2. Валидация билета. Система проверяет:
● билет вообще был выпущен;
● он продан, а не подделка;
● он ещё не проходил (защита от копий).
3. Проверка зоны доступа. Система смотрит, соответствует ли билет этому входу. Если билет в VIP-ложу, а человек стоит у обычного входа — контролёр увидит это на экране.
4. Регистрация прохода. Система фиксирует: этот билет прошёл, время входа, какое устройство сканировало.
5. Синхронизация. Данные о проходе уходят на сервер, а на устройство загружаются обновления — новые билеты, изменения в базе.
Что здесь «тяжёлое», а что «лёгкое»:
|
Операция |
Что происходит |
Почему такая |
|
Проверка билета |
Сканирование + валидация + проверка зоны + регистрация прохода |
Тяжёлая — нужно несколько запросов к базе, ждать ответа |
|
Синхронизация |
Загрузка новых билетов на устройство + отправка проходов на сервер |
Тяжёлая — большой объём данных, зависит от сети |
|
Сканирование без синхронизации |
Только проверка и регистрация локально |
Лёгкая — меньше запросов, быстрее ответ |
Именно поэтому в тестах 200 RPS — это подтверждённый порог на тяжёлых операциях, а 250 RPS — на лёгких. В лёгких сценариях фиксировались значения до 350–400 RPS.
Какие были ограничения
|
Что мешало |
Как мы с этим работали |
|
При 45 000 записей зависания интерфейса только на Xiaomi — на других Android-смартфонах и iPhone таких проблем не было |
Перешли с Key Value Storage на SQLite + Drift, добавили миграции и индексы |
|
Бэкенд не справлялся с объёмом запросов |
Частично отказались от SQLAlchemy в пользу прямых запросов, профилировали, переработали индексы |
|
Нужно было работать без интернета — в том числе в сценарии «большой стадион + полное отсутствие связи» |
Реализовали офлайн-валидацию: данные загружаются заранее, проходы фиксируются локально, синхронизация идёт при появлении связи |
|
Зоопарк билетных систем у партнёров |
Унифицировали интеграцию через единый интерфейс, научились дообогащать данные |
|
Сопротивление со стороны конкурента |
Сфокусировались на технической части — сделали свою работу качественно |
|
Срок — 4 месяца |
Начали с архитектуры и параллельно тестировали на реальном оборудовании |
Что мы сделали
Команда АЙТИФОКС разработала облачную платформу управления мероприятиями и билетами для стадиона «Крылья Советов».
Ключевые компоненты:
● Облачная платформа на Python (бэкенд) — микросервисная архитектура, работа с PostgreSQL.
● Мобильное приложение и веб-версия на Flutter — единая кодовая база для нативного приложения и браузера.
● Мобильные сканеры и ТСД (терминалы сбора данных) — устройства, которые контролёры используют для проверки билетов на площадках без инфраструктуры. Работают на Android, iPhone (включая Safari) и в браузере.
● Интеграция с билетными системами — поддержка нескольких билетных ядер, возможность дообогащения данных.
● Офлайн-режим — работа без интернета с последующей синхронизацией.
● Аналитика — мониторинг загрузки площадок и потоков посетителей.
Главные технические решения
Переход с Key Value Storage на SQLite + Drift. Сначала мы хранили билеты в простом хранилище — оно подходит для небольших объёмов, но не для серьёзной нагрузки. Когда билетов стало 45 000, на телефонах Xiaomi начались зависания интерфейса, особенно при открытии клавиатуры. На других устройствах — iPhone и Android-смартфонах других производителей — таких проблем не было.
Попробовали разные варианты простых хранилищ, но одни не работали в браузере, другие устарели. Тогда мы поставили на устройство полноценную базу данных — SQLite. Для Flutter использовали пакет Drift, который помогает с ней работать. Добавили механизм обновления структуры данных (миграции) и ускорили поиск (индексы).
Теперь система стабильно работает с тестовой базой до 50 000 билетов. Реальный стадион «Крылья Советов» вмещает около 45 000 зрителей.
Единая кодовая база для нативного приложения и веба. Приложение работает не только нативно, но и в браузере — Chrome, Firefox или Safari на телефоне. Кодовая база идентична, дублирования нет. Это важный плюс: не нужно поддерживать две версии.
Оптимизация бэкенда. Когда билетов стало 45 000, сервер не справлялся с объёмом запросов. Причина была в SQLAlchemy — инструменте для работы с базой данных. Он удобный, но создавал лишнюю нагрузку: запросы выполнялись медленнее, чем могли бы. Мы разобрались, где именно теряется скорость, и частично заменили SQLAlchemy на прямые запросы к базе. Переработали индексы — это ускорители поиска. После этого сервер стал держать нагрузку.
Защита от копий билетов. Система обращается к билетному ядру, понимает, какие билеты были выпущены. Считывается штрих-код или QR-код с мобильного телефона или ТСД. Если билет уже прошёл — система не пустит, а если билет не соответствует входу (например, VIP-ложа) — контролёр увидит это на экране.
Какие инструменты использовали
● Python — бэкенд, микросервисная архитектура.
● Flutter — фронтенд для нативного приложения и веб-версии.
● SQLite + Drift — локальное хранилище на клиенте.
● PostgreSQL — основная база данных.
● gRPC — взаимодействие между клиентом и сервером.
● Yandex Tank + Pandora — нагрузочное тестирование.
Как мы работали
Проект занял около 4 месяцев. Команда: один бэкендер, один фронтенд, тестировщик, архитектор и менеджер.
Типичный цикл:
● Проектировали архитектуру и логику работы с офлайн-режимом.
● Реализовывали клиентскую часть на Flutter, синхронизацию с бэкендом.
● Тестировали на реальном оборудовании — мобильные устройства, ТСД.
● Обнаруживали проблему (например, зависания на Xiaomi) — искали причину, исправляли.
● Проводили нагрузочное тестирование: 50 000 билетов, 224 852 прохода за один прогон.
● Выявляли узкие места — фиксировали и передавали в оптимизацию.

Итог
АЙТИФОКС разработал и протестировал облачную СКУД для стадиона «Крылья Советов».
Что мы обеспечили:
● 50 000 билетов и 224 852 прохода за один тестовый прогон — искусственная нагрузка с запасом. Реальный стадион — 45 000 мест.
● Подтверждённая скорость — около 40 проходов/с на тяжёлых операциях (≈2 400 проходов/мин).
● Целевой пиковый ориентир — 140 проходов/с (8 400 проходов/мин).
● 200 RPS — подтверждённый порог на самых тяжёлых операциях. В лёгких тестах фиксировались 350–400 RPS.
● 250 RPS — максимальная пропускная способность на лёгких операциях (подтверждено нагрузочным тестированием). В отдельных лёгких тестах фиксировались значения до 350–400 RPS.
● 0 ошибок — на проверке билета и массовой регистрации проходов.
● Единая кодовая база — нативное приложение и веб-версия без дублирования.
● Офлайн-режим — работает без интернета, синхронизируется при восстановлении связи.
● Интеграция с билетными системами — поддержка нескольких ядер, дообогащение данных.
Нагрузочное тестирование:
|
Сценарий |
Объём данных |
RPS |
Успешность |
Средняя задержка |
|
Проверка билета |
50 000 билетов |
200 |
100% |
412 мс |
|
Регистрация проходов |
50 000 билетов / 224 852 прохода |
200 |
100% |
412 мс |
|
Синхронизация событий |
50 000 билетов + 224k проходов |
200 |
100% |
6 724 мс |
Отдельно зафиксирован целевой пиковый сценарий — 140 проходов/с (8 400 проходов/мин). Он требует подтверждения отдельным нагрузочным тестом и находится в зоне оптимизации.
Пояснение по нагрузке: 50 000 билетов и 224 852 прохода — тестовая база за один прогон. На один билет приходится 2–4 прохода (вход, выход, повторный вход). С учётом 5 запросов на один проход подтверждённый порог — 40 проходов/с на тяжёлых операциях, это около 2 400 в минуту. Для пикового запаса 140 проходов/с (8 400/мин). На лёгких операциях (сканирование без синхронизации) подтверждённый порог — 250 RPS; в отдельных лёгких прогонах фиксировались 350–400 RPS.
Честно о зонах роста: отдельные стресс-тесты помогли выявить зоны роста. Мы зафиксировали их и продолжаем работать над оптимизацией.
Почему тестовая база 50 000 билетов — это не «маленький объём»
Может показаться, что 50 000 билетов — это немного. Но это больше, чем реальная вместимость стадиона (45 000 мест). А 224 852 прохода — это в 2,5 раза больше, чем даёт один реальный матч:
- Реальный матч: 45 000 зрителей × 2 прохода (вход + выход) = 90 000 проходов.
- Тестовая база: 224 852 прохода — это как два с половиной матча подряд.
Запас нужен по трём причинам:
1. Стадион может принимать больше. Концерты и другие события собирают больше зрителей, чем футбольный матч.
2. Повторные проходы. Человек может выйти и вернуться — это дополнительные операции.
3. Будущие площадки. Система должна работать не только на «Крыльях Советов», но и на объектах с большей вместимостью.
Поэтому тестовая база — это не «маленький объём», а проверка с запасом, которая показывает: система выдержит не только текущий стадион, но и более крупные объекты.
Почему «простая» система контроля доступа оказалась непростой
Часто заказчики думают: «У нас есть билеты, нужно просто сканировать их на входе. Что тут сложного?» На деле именно в таких задачах всплывают главные риски: нагрузка на клиенте, офлайн-режим, интеграция с чужими системами.
В проекте для «Крыльев Советов»:
● Решили проблему производительности на устройствах Xiaomi — перешли на SQLite + Drift.
● Оптимизировали бэкенд — отказались от части SQLAlchemy.
● Провели нагрузочное тестирование — нашли пределы и узкие места.
● Обеспечили работу без интернета — с синхронизацией при восстановлении связи.
АЙТИФОКС разрабатывает системы автоматизации с внешними API, сложной бизнес-логикой и интеграциями с существующими IT-системами заказчика. Видим проект целиком: анализируем данные, проектируем архитектуру, тестируем на реальных нагрузках и доводим систему до рабочего состояния.
Если у вас есть задача по контролю доступа, управлению мероприятиями или интеграции с билетными системами — напишите нам. Обсудим вашу задачу.
Технологии
Часто задаваемые вопросы
Кейсы, которыми мы гордимся


