Наша команда спеціалізується на розробці сайту фітнес-клубу на 1С-Бітрікс. У цій статті ми розповімо, як спроектувати високонавантажений сайт фітнес-клубу на 1С-Бітрікс, який витримає пікові навантаження. Клієнт заходить на сайт фітнес-клубу в понеділок увечері, обирає заняття, натискає «Записатися» — і бачить «Помилка сервера». Або розклад відкривається через 5 секунд. Архітектура не розрахована на пікові навантаження. Ми — команда інженерів з 8-річним досвідом розробки на 1С-Бітрікс — вирішуємо ці проблеми під ключ. Ми гарантуємо якість: усі наші рішення мають сертифікат 1С-Бітрікс. Проектуємо Highload-структури, налаштовуємо кешування, інтегруємо з платіжними системами та CRM. Оцінимо ваш проєкт за 2 дні, терміни озвучимо після аудиту. Вартість проєкту розраховується індивідуально. Економія при розробці з нашим підходом є значною. Щоб отримати консультацію щодо вашого проєкту, зв'яжіться з нами.
Типове завдання: розклад на тиждень з 300 заняттями, 15 залів, 40 тренерів. Без правильного підходу фільтрація займає 800–1200 мс. Ми переводимо дані в Highload-блоки — плоскі таблиці з індексами. Час фільтрації падає до 20–30 мс. Highload-блоки виграють у інфоблоків у 45 разів за швидкістю фільтрації. Нижче розберемо ключові вузли такого проєкту.
Як спроєктувати розклад під навантаження 5000 відвідувань на день?
Розклад — центральний елемент сайту. Якщо він гальмує, клієнт іде в Telegram-бота конкурента.
Для зберігання розкладу використовуємо HL-блоки. Звичайний інфоблок (EAV-модель) при 300 заняттях, 15 залах і 40 тренерах дає десятки тисяч рядків у таблиці властивостей. Фільтрація за комбінацією «зал + день + тренер + напрямок» — серія JOIN-ів з 800–1200 мс.
Highload-блок — плоска таблиця в MySQL. Один рядок = одне заняття, всі поля — колонки. Фільтрація через звичайні індекси. Для прискорення запитів ми створюємо складені індекси на UF_DATE, UF_HALL_ID та UF_TRAINER_ID.
Структура 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
}
ORM Бітрікса не підтримує 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.
Економія на розробці з нашим підходом є значною у порівнянні з типовими рішеннями, а бюджет проєкту визначається індивідуально.
Інтеграція з 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 років на ринку. Високонавантажені розклади — наша спеціалізація.
Перед стартом визначте мастер-систему розкладу та платіжний шлюз — це впливає на архітектуру. Отримайте консультацію: зв'яжіться з нами, щоб обговорити деталі.







