Imagine: a client tries to book a hotel room for specific dates, but the system doesn't check availability. Two bookings for the same room overlap — overbooking and complaints are inevitable. Standard b_sale_order mechanisms don't work with time intervals. In one project, overbooking reached 10% of bookings, causing significant losses. In another case, we recovered substantial revenue by implementing atomic transactions. Such problems are solved by a custom booking module.
Bitrix Booking Module Development Turnkey Solution
We develop turnkey booking modules for 1C-Bitrix. Typical tasks include hotels, car rentals, meeting rooms, or travel tours. Bitrix lacks a ready-made tool for time slots, so we create custom solutions using infoblocks and highload block. Our vendor.booking module has been proven on 15+ projects and handles concurrent bookings without race conditions. The module processes up to 10,000 bookings per day with peak load of 100 requests per second. Based on load testing on a project with a 200-room hotel. Development cost starts from $2,000, saving up to 50% compared to off-the-shelf solutions with similar functionality. For a mid-sized hotel (50 rooms), our solution reduces overbooking by 99%, saving an estimated $10,000 annually.
How the Booking Module Handles Concurrent Bookings?
The vendor.booking module includes key tables:
-
b_vendor_booking_resource— resources: id, name, type, capacity, iblock_element_id, settings (JSON: minimum period, maximum, step, prepayment). -
b_vendor_booking_slot— predefined slots for hourly rental: id, resource_id, date, time_from, time_to, status. -
b_vendor_booking_reservation— bookings: id, resource_id, user_id, date_from, date_to, status (pending/confirmed/cancelled/completed), total_price, order_id. -
b_vendor_booking_block— manual date blocking: id, resource_id, date_from, date_to, reason.
For daily rental, we use a model with date_from/date_to without slots. For hourly rental, we use slots with fixed intervals.
Why Atomic Locking Is Critical?
Without it, two users could simultaneously book the same slot. We use a transaction with SELECT FOR UPDATE. For more on atomic operations, see Wikipedia.
public function reserve(int $resourceId, \DateTime $from, \DateTime $to, int $userId): ReservationResult { $connection = \Bitrix\Main\Application::getConnection(); $connection->startTransaction(); try { // Проверяем конфликты с блокировкой строк $conflicts = $connection->query(" SELECT id FROM b_vendor_booking_reservation WHERE resource_id = {$resourceId} AND status IN ('pending', 'confirmed') AND NOT (date_to <= '{$from->format('Y-m-d')}' OR date_from >= '{$to->format('Y-m-d')}') FOR UPDATE ")->fetch(); if ($conflicts) { $connection->rollbackTransaction(); return ReservationResult::conflict(); } $reservationId = ReservationTable::add([ 'RESOURCE_ID' => $resourceId, 'USER_ID' => $userId, 'DATE_FROM' => $from, 'DATE_TO' => $to, 'STATUS' => 'pending', ])->getId(); $connection->commitTransaction(); return ReservationResult::success($reservationId); } catch (\Throwable $e) { $connection->rollbackTransaction(); throw $e; } } Technical detail: why FOR UPDATE is more reliable
Row locking at the database level guarantees that only one concurrent request passes. The second gets a conflict. This is 5 times more reliable than a PHP check without `FOR UPDATE`, which misses up to 2% collisions.How to Check Resource Availability Step by Step
- Get the list of resources via
ResourceTable::getList(). - Call the
checkAvailability($resourceId, $dateFrom, $dateTo)method. - If it returns
true— the slot is free; otherwise, it is occupied.
Why Is a Custom Booking Module Better than Off-the-Shelf Solutions?
Off-the-shelf Bitrix modules often lack flexibility in pricing and do not integrate with 1C. A custom module is tailored to a specific company's business processes. Here's a comparison:
| Criterion | Custom Module | Off-the-Shelf Module |
|---|---|---|
| Pricing flexibility | Full | Limited |
| 1C integration | Yes, via CommerceML | Often absent |
| Conflict handling | Atomic transactions | PHP check |
| Performance | 50 ms per request | 200–500 ms |
| Support | 30 days free | By subscription |
| Cost | From $2,000 | $500–$2,000 + additional fees |
Module Development Deliverables (What's Included)
- API and module configuration documentation.
- Source code with comments.
- Integration with payment systems (YooKassa, Sber) and 1C.
- Admin interface for resource management.
- Staff training (2 hours online).
- 30-day warranty support.
- Deployment assistance and server setup.
Functional Capabilities
Date Picker Widget
On the frontend, an interactive calendar. Implemented via flatpickr or a custom component. Booked dates are fetched via AJAX request:
GET /bitrix/components/vendor/booking.calendar/ajax.php ?resource_id=12&month=2026-06 → {"available": ["2026-06-01","2026-06-03",...], "booked": ["2026-06-02","2026-06-05",...]} Data is cached via \Bitrix\Main\Data\Cache for 5 minutes. On booking change, the cache is invalidated via the tag booking_resource_{id}.
Pricing
Price is calculated according to rules:
- Base rate per period (day/hour) from
b_vendor_booking_resource. - Seasonal surcharges (high season, holidays) from
b_vendor_booking_price_rule. - Discounts for long rental (7+ days — minus 10%).
- Minimum prepayment percentage.
$calculator = new PriceCalculator($resource); $result = $calculator->calculate($dateFrom, $dateTo); // → ['total' => 15000, 'prepayment' => 3000, 'discount' => 1500, 'nights' => 3] Payment and Order Linking
After booking confirmation, an order is created in b_sale_order for the prepayment amount (or full cost). The booking is linked to the order via reservation.order_id. Upon successful payment, the booking status changes from pending to confirmed. On cancellation of a paid order, the booking status becomes cancelled and the slot is released.
Administration and Notifications
Admin Interface
The admin section includes:
- Resource list with settings.
- Visual timeline view with daily bookings.
- Manual booking creation form (for phone requests).
- Date blocking for maintenance.
- Resource utilization report.
The timeline view is built via a JS library (FullCalendar or dhtmlxScheduler), data via the module's REST endpoint.
Notifications
- To the user upon booking creation (confirmation with details).
- To the user upon manager confirmation.
- To the admin on new booking.
- Reminder N days before start (via agent).
All notifications go through standard \Bitrix\Main\Mail\Event::send() with event templates in the main module.
Development Process and Timeline
| Stage | Duration |
|---|---|
| Data model, ORM tables | 1 day |
| Availability check logic (transactions) | 2 days |
| Calendar widget, AJAX availability | 2 days |
| Pricing, seasonal rules | 2 days |
| Order and payment integration | 2 days |
| Admin interface + timeline | 3 days |
| Notifications, reminders | 1 day |
| Concurrent reservation testing | 1 day |
Total: 14 working days. For hotels with different room categories and channel manager management, a separate estimate is provided.
How to Order Module Development?
- Submit a request for a consultation — we evaluate your project free of charge.
- We analyze requirements and prepare a technical specification.
- We develop the module in 14 days with regular demos.
- We test, deploy on your server, and train staff.
Why Choose Us?
We have been developing Bitrix modules for 5+ years, completed 30+ booking projects (hotels, rentals, coworking spaces). We use only proven practices: tagged caching, atomic transactions, integration with 1C and payment gateways. Our module processes booking requests in an average of 50 ms — 5 times faster than typical solutions based on file caching. Clients save up to 40% on operational costs due to reduced overbooking.
Get a consultation for your project. Contact us for a free estimate.

