A custom booking system for services, and why plugins break
Nearly every booking project starts as a plugin that worked fine for a year. What breaks it is never the booking form. It is the second member of staff, or the first hour that does not exist.
Booking looks like the most solved problem in software. Pick a slot, take a name, send a confirmation. There are hundreds of plugins and most of them work.
They work for one resource with one calendar. The moment availability is the intersection of several things, a room and a person and a piece of equipment, the model underneath most plugins stops describing the business, and the symptoms show up as double bookings rather than as error messages.
What you are really modelling
A booking is not an entry in a calendar. It is a claim on one or more scarce resources for an interval, which must not overlap another claim on the same resource.
Write it that way and the hard parts become visible immediately. What are the resources. Which combinations are required for which service. What counts as an overlap when a treatment needs fifteen minutes of cleaning afterwards that the customer never sees.
Most plugins model a calendar instead, which is why their multi-staff support tends to be a list of separate calendars with no concept of a shared resource between them.
The five places plugins actually break
- Multi-staff with different skills. Any stylist can do a cut, two can do colour, one does both and only on Tuesdays. This is a constraint problem and a per-person calendar cannot express it.
- Buffers and setup time. The customer books 60 minutes; the resource is occupied for 75. Systems that model only the visible appointment will sell the overlapping slot.
- Capacity that is not one. A class takes twelve people and a room takes twenty. One booking consumes one of twelve, not the whole interval.
- Cancellation and rescheduling rules that mean something. A real policy has a cut-off, a fee, and a record of who changed what. Most plugins have a checkbox.
- Anything that must reconcile with payment. A slot held by an unpaid booking is the most expensive bug in this category, because it is invisible until the day.
Only the first two usually appear in the brief. The other three are discovered in month three, which is the argument for scoping the data model properly even when the first version is small.
Time zones are harder than they look, and the standards say so
If every customer and every member of staff is in one city, skip this section. If either is not, this is the part that will cost you, and it is not a matter of storing UTC and moving on.
The rules for recurring events and local time are specified rather than improvised. RFC 5545, the iCalendar specification, requires a separate VTIMEZONE component for each unique time zone identifier an object references, and defines the two genuinely awkward cases directly. When a local time occurs twice because the clocks go back, the value refers to the first occurrence. When a local time does not exist at all because the clocks went forward, it is interpreted using the UTC offset in force before the gap.
Those two sentences are the bugs. A weekly nine o'clock appointment crosses a daylight saving boundary and either happens twice or does not exist, and a naive implementation resolves it differently from the customer's phone.
And the rules themselves move. The IANA time zone database, which is what almost every platform resolves local time against, is at release 2026d, published on 11 September 2026. Recent changes in that release include Canada's Northwest Territories moving to permanent UTC minus six. Governments change offsets and daylight saving rules with months of notice, sometimes weeks.
The practical consequence: store the instant in UTC and also store the time zone identifier the booking was made in, never the offset. An offset is a fact about one moment. A zone identifier survives a rule change, and a stored offset quietly becomes wrong the next time a government legislates.
What to buy and what to build
| Part | Decision | Why |
|---|---|---|
| Calendar UI | Buy or use a library | Solved, and expensive to polish yourself |
| Availability engine | Build | This is your business rules and nothing generic fits |
| Time zone handling | Use the platform library | Never hand-roll offset arithmetic |
| Notifications | Buy | Deliverability is somebody else's full-time problem |
| Payments | Buy | Never build; compliance alone settles it |
| Staff and resource model | Build | The part plugins get wrong |
The shape of that answer is typical rather than special, and it is the same reasoning we apply in custom software vs off the shelf: build the part that is your business and buy the parts that are everybody's.
Scoping a first version honestly
A first version that handles your real constraints for one location is a few weeks of work, not a quarter, provided the scope is held. What makes it a quarter is adding a customer account area, a loyalty scheme and a reporting suite before the booking logic is right.
- Model resources and services and the required combinations. This is the whole project.
- Availability with buffers, working hours and exceptions such as leave and holidays.
- One booking flow, one confirmation, one reschedule path with a real cut-off.
- An internal view that staff will actually use, which usually means a day view by resource.
- Store instant plus zone identifier from the first line of code, because retrofitting this is a migration.
Leave out reminders beyond a basic one, any mobile app, and reporting. Those are additions once bookings are trustworthy, and they are the usual route to a project that is eighty percent done for five months. The discipline for holding that line is in how to scope a software project.
When you should not build this
Three honest cases. If you have one practitioner and one room, a plugin is the right answer and will stay right for years. If your scheduling is genuinely standard for a well-served industry, a vertical product will beat a custom build on price and on features you have not thought of yet. And if the real problem is that nobody answers the phone, a booking system will not fix it.
The sector products are worth a serious look before committing, and we have scoped two of them module by module in a clinic management system and a training centre management system, both of which contain scheduling as one part of something larger. If scheduling is all you need, that is an argument for a smaller build, not a bigger purchase.
Describe it. We build it.
Seven or twelve days, pay on delivery, a year of maintenance included. Bring the problem, not a spec.
Book a meetingRead next
A restaurant order management system, scoped around the channels
A restaurant order management system earns its keep by consolidating channels, not by taking orders. What it must own, and what the tax receipt forces.
ReadAn AI chatbot for a business website, and where it loses the lead
An AI chatbot for a business website helps or loses the lead on three things: grounding, escalation and disclosure. What to build, and what to skip entirely.
Read