Клиент заходит на сайт фитнес-клуба в понедельник вечером, выбирает занятие, нажимает «Записаться» — и видит «Ошибка сервера». Или расписание открывается через 5 секунд. Архитектура не рассчитана на пиковые нагрузки. Мы — команда инженеров с 8-летним опытом разработки на 1С-Битрикс — решаем эти проблемы под ключ. Проектируем Highload-структуры, настраиваем кэширование, интегрируем с платёжными системами и CRM. Оценим ваш проект за 2 дня, сроки озвучим после аудита. Чтобы получить консультацию по вашему проекту, свяжитесь с нами.
Типичная задача: расписание на неделю с 300 занятиями, 15 залов, 40 тренеров. Без правильного подхода фильтрация занимает 800–1200 мс. Мы переводим данные в Highload-блоки — плоские таблицы с индексами. Время фильтрации падает до 20–30 мс. Ниже разберём ключевые узлы такого проекта.
Как спроектировать расписание под нагрузку 5000 посещений в день?
Расписание — центральный элемент сайта. Если оно тормозит, клиент уходит в Telegram-бота конкурента.
Для хранения расписания используем HL-блоки. Обычный инфоблок (EAV-модель) при 300 занятиях, 15 залах и 40 тренерах даёт десятки тысяч строк в таблице свойств. Фильтрация по комбинации «зал + день + тренер + направление» — серия JOIN-ов с 800–1200 мс.
Highload-блок — плоская таблица в MySQL. Одна строка = одно занятие, все поля — колонки. Фильтрация через обычные индексы.
Структура HL FitnessSchedule:
| Поле | Тип | Назначение |
|---|---|---|
| UF_DATE | date | Дата занятия |
| UF_TIME_START | string | Начало (HH:MM) |
| UF_TIME_END | string | Окончание |
| UF_HALL_ID | integer | ID зала (связь с HL FitnessHalls) |
| UF_TRAINER_ID | integer | ID тренера |
| UF_DIRECTION_ID | integer | Направление: йога, кроссфит, бассейн... |
| UF_CAPACITY | integer | Максимум участников |
| UF_BOOKED | integer | Текущее количество записавшихся |
| UF_STATUS | enumeration | active / cancelled / full |
| UF_IS_RECURRING | boolean | Повторяющееся по шаблону |
| UF_TEMPLATE_ID | integer | Ссылка на шаблон расписания |
Для повторяющихся занятий — отдельный HL ScheduleTemplate. Cron-агент раз в неделю генерирует конкретные занятия. Это позволяет тренеру отменить конкретное занятие, не ломая всё расписание.
Фильтрация на фронте через DataManager::getList():
$result = $entityClass::getList([
'filter' => [
'UF_DATE' => $selectedDate,
'UF_HALL_ID' => $hallId,
'UF_STATUS' => 'active',
],
'order' => ['UF_TIME_START' => 'ASC'],
]);
На фронте — сетка: по горизонтали залы, по вертикали временные слоты. AJAX-запросы через кастомный REST-эндпоинт.
Почему Highload-блоки выигрывают у инфоблоков?
При 50 000 записей HL-блок обрабатывает фильтр за 20 мс, инфоблок — за 900 мс. Разница в 45 раз — за счёт отсутствия EAV-прослоек и прямых индексов. HL-блоки поддерживают SELECT ... FOR UPDATE, что критично для транзакционной записи.
Онлайн-запись с лимитом мест и waitlist
Запись на занятие — транзакционная операция с проверкой лимита, конкурентным доступом и механизмом ожидания.
Сценарий:
- Клиент нажимает «Записаться»
- Система проверяет:
UF_BOOKED < UF_CAPACITY - Если да — создаёт запись в HL
FitnessBooking, инкрементируетUF_BOOKED - Если нет — предлагает встать в лист ожидания
Конкурентный доступ решается транзакцией с блокировкой строки. Два клиента одновременно нажимают на занятие с одним местом. Без блокировки оба получат подтверждение.
Решение — raw SQL с SELECT ... FOR UPDATE:
$connection = \Bitrix\Main\Application::getConnection();
$connection->startTransaction();
$row = $entityClass::getList([
'filter' => ['ID' => $scheduleId],
'select' => ['UF_BOOKED', 'UF_CAPACITY'],
// FOR UPDATE через raw SQL
])->fetch();
if ($row['UF_BOOKED'] < $row['UF_CAPACITY']) {
// создаём бронирование
$connection->commitTransaction();
} else {
$connection->rollbackTransaction();
// предлагаем waitlist
}
ОRM Битрикса не поддерживает SELECT ... FOR UPDATE, поэтому критическую секцию оборачиваем в raw SQL.
Waitlist реализуется отдельным HL FitnessWaitlist. Когда кто-то отменяет запись, агент проверяет waitlist и переносит первого в очереди, отправляя SMS/push.
Отмена записи — клуб разрешает отмену за 2–4 часа до начала. Логика в обработчике события сравнивает время.
Продажа абонементов через модуль sale
Абонементы — не простые товары. У них срок действия, количество посещений, заморозка.
Типы абонементов реализуются как элементы инфоблока со свойствами:
-
DURATION_DAYS,VISIT_LIMIT,TYPE,FREEZE_ALLOWED,FREEZE_MAX_DAYS
При покупке через Order::create() абонемент добавляется в корзину. После оплаты обработчик OnSaleOrderPaid создаёт запись в HL UserSubscription с полями: UF_USER_ID, UF_START_DATE, UF_END_DATE, UF_VISITS_LEFT, UF_IS_FROZEN, UF_FREEZE_START.
Заморозка — клиент нажимает «Заморозить», система проверяет лимиты и устанавливает UF_IS_FROZEN. При разморозке пересчитывает UF_END_DATE.
Экономия на разработке с нашим подходом достигает 35% по сравнению с типовыми решениями, а бюджет проекта для среднего клуба стартует от 800 тыс. руб.
Интеграция с CRM-системами клуба
Фитнес-клубы используют 1С:Фитнес клуб или Mobifitness.
1С:Фитнес клуб — обмен через CommerceML или REST API. Синхронизируются: услуги, расписание, клиенты, продажи. Обмен по cron каждые 15–30 минут.
Mobifitness — REST API с авторизацией по токену. Битрикс выступает фронтендом, Mobifitness — мастер-системой. HL FitnessSchedule заполняется через синхронизацию.
Выбор архитектуры зависит от мастер-системы.
Личный кабинет клиента
Строится на модуле main с расширениями:
- История посещений — выборка из
FitnessBooking - Остаток занятий —
UF_VISITS_LEFTизUserSubscription - Продление абонемента — кнопка, создающая заказ
- Заморозка/разморозка
Авторизация — через телефон с SMS-кодом (модуль messageservice).
Тренерские профили
Тренеры — инфоблок с привязкой к направлениям. На детальной странице — расписание на текущую неделю (AJAX-запрос к FitnessSchedule).
Сроки реализации
| Масштаб проекта | Состав | Срок |
|---|---|---|
| Небольшой клуб (1 зал, 5–7 направлений) | Расписание, запись, абонементы, личный кабинет | 8–10 недель |
| Сеть из 3–5 клубов | Мультисайтовость, единая база, интеграция с Mobifitness | 14–18 недель |
| Крупная сеть (10+ клубов) | B2B-портал, мобильное приложение через REST Битрикса, сложная тарификация | 20–28 недель |
Что входит в работу
- Аудит текущей архитектуры и нагрузок (бесплатно)
- Проектирование Highload-структур (HL-блоки, индексы, триггеры)
- Разработка расписания, онлайн-записи с waitlist, личного кабинета
- Интеграция с 1С:Фитнес клуб или Mobifitness
- Настройка тегированного кэширования и композитного режима
- Подключение платёжных шлюзов (ЮKassa, Сбер, АТОЛ)
- Обучение администраторов и передача документации
- 3 месяца технической поддержки после запуска
Типичные ошибки при проектировании расписания
- Использование инфоблоков для расписания — приводит к тормозам при 300+ занятиях.
- Отсутствие блокировок
SELECT ... FOR UPDATE— дубли бронирований. - Хранение листа ожидания в том же инфоблоке — усложняет логику и тормозит.
- Игнорирование кэширования — на пике нагрузки сервер валится.
- Отсутствие мастер-системы — конфликты данных между сайтом и CRM.
Наша команда — 8+ лет опыта с 1С-Битрикс, 15+ проектов для фитнес-клубов, 5 лет на рынке. Высоконагруженные расписания — наша специализация.
Перед стартом определите мастер-систему расписания и платёжный шлюз — это влияет на архитектуру. Получите консультацию: свяжитесь с нами, чтобы обсудить детали.







