Skip to content
Turnaround

Fixing a live salon booking system

An Australian salon was taking bookings through a system with broken booking rules, missing messages and heavy mobile pages. I took over the existing product, fixed 31 documented defects and rebuilt the customer website while working across the backend and staff tools.

Market
Salon booking, Australia
My role
Lead engineer, owned end to end
Scale
200 to 300 bookings a month
Starting point
31 documented defects

ProblemThe salon's existing system had booking errors, missing notifications and a heavy customer website.

What I didI repaired the inherited backend, rebuilt the customer site, separated the staff admin and fixed the booking lifecycle.

ResultI fixed 31 documented defects, added working reminders and reduced the mobile page from 17.2 MB to 1.7 MB.

Documented defects
31 to fix31 fixed

Repairs across the inherited booking system and its supporting workflows.

Mobile page payload
17.2 MB1.7 MB

Page weight reduced through smaller media, an icon subset and asset changes.

Appointment reminders
No working reminders24 hours + 2 hours

Configurable email and SMS reminders before the appointment.

The problem

The salon needed the booking journey repaired as a whole

The salon already had customers booking online. The system was not an empty project that I could design without existing behaviour to consider. It had customer pages, staff tools and a backend built by another team. I took over that first version and worked across the product. The immediate task was to make the booking journey dependable, including what happened after a customer pressed confirm.

The defects crossed several parts of the business. Past appointment times could appear as available. Cancelled bookings continued to block slots. Messages were missing, and daily income used the wrong time zone. The mobile page carried a large download. I fixed the documented list of 31 defects, rebuilt the customer website and separated the staff admin. I treated this as work on an operating business, with existing bookings and staff workflows to preserve and understand.

What to fix first

I ordered the work around the consequences of a mistake

A defect list is useful, but it is not a delivery order. Some faults affect which actions the system accepts. Others affect booking amounts, availability, messages or page speed. I worked through the repairs in priority order. The customer-facing appearance mattered, but it could not substitute for correct booking behaviour. A smaller page is useful only if the appointment it helps someone make is valid.

I kept the inherited backend and repaired it rather than replace the whole product at once. I did rebuild the customer website, because that was a separate part of the work with its own needs. Those choices were compatible. A takeover does not require treating every existing component as permanent, or treating every component as disposable. I chose the boundary according to the job each part needed to do.

The work covered the customer site, staff admin and backend. That made it possible to follow a change across the journey. A cancellation affects the customer dashboard, the availability calculation and the staff notification. Repairing only the visible button would leave the business problem incomplete. I used the booking lifecycle as the connection between those pieces, rather than judging completion by whether an individual screen looked finished.

There was also a practical limit on claims about improvement. I could describe the rules I changed, the notifications I added and the payload I reduced. I did not have a measured increase in revenue or a measured reduction in missed appointments to attach to the work. I kept the result tied to those concrete changes, because they explain what the salon received without guessing what happened afterwards.

The fix log

The repairs followed the life of an appointment

Booking selection

BeforeCustomers could select past times or a service unavailable at the chosen branch.

AfterPast slots are hidden, with branch-service availability checked on the server and explained in the interface.

Cancellation

BeforeCancelled bookings continued to block their appointment slots.

AfterCancelled slots are released, with self-service cancellation and a recorded reason.

Business time

BeforeAvailability and daily figures used the wrong time-zone interpretation.

AfterStored booking times are interpreted in Australia/Hobart, including the meaning of today.

Booking messages

BeforeConfirmations, change notices and cancellation messages were missing.

AfterCustomer notices and staff alerts are part of the booking workflow.

Reminders

BeforeFailed reminder attempts could be recorded as complete.

AfterA reminder is marked sent after a channel succeeds; unsuccessful sends remain eligible for a later attempt.

Email content

BeforeMessages needed delivery and presentation repairs.

AfterPlain-text content, image fallbacks and a repaired support link make the emails more usable.

Booking rules

The server needed to understand the branch and service

The business offers services at different branches. A service in the general catalogue is not automatically available at every location. I added branch-service checks on the server and warnings in the customer interface. The warning helps someone choose correctly. The backend check is what makes the rule apply when the booking is created. Both belong to the same behaviour, but they serve different purposes.

I rebuilt the customer booking journey as a 5-step flow. It includes a saved cart, service selection, branch choice, date and time selection, customer information and confirmation within that journey. The cart keeps selected services between visits. That is useful when a customer leaves the page and returns. I kept that convenience alongside the booking checks, because saved selections still need to make sense when the customer completes the appointment.

I also worked on combo deals and an invoice snapshot in the booking context. The summary needs to reflect what the customer is actually booking, rather than loosely assemble a price from unrelated screen state. I repaired confirmation paths so they did not end without a clear outcome. A booking flow needs to communicate completion as well as collect the information required to create the booking.

These were connected repairs. Valid branch choices, valid time choices and a clear confirmation all contribute to an appointment that staff can act on. I did not treat the flow as a set of isolated form fields. The useful question was whether the selected service could be delivered at the chosen branch and time, with the customer able to understand the result.

Cancellation

A cancelled appointment had to return its slot

A cancelled booking had been continuing to block availability. That leaves the record in a cancelled state while the calendar still behaves as though the appointment exists. I fixed the availability handling so cancelled slots are released. The business meaning of cancellation needed to reach the next customer's booking choices, rather than stop at a status label in the staff screen.

I added self-service cancellation and a cancellation reason. The customer can manage the booking through their dashboard, and staff receive the corresponding notice. The reason provides context for the change. This is a small example of why I followed actions through the whole system: the customer action, calendar behaviour and staff message all need to agree about what happened.

Releasing a slot makes it available to be booked again. That is the result I can state directly. It does not establish how often another customer filled the gap or what revenue followed. The repair removes an incorrect block in availability. For an operating salon, that is useful behaviour in its own right, without attaching an unmeasured sales figure to it.

Time zones

Today had to mean today at the salon

The system stored booking times as local wall-clock values, but calculated availability using the server's time zone. Those values need a business context before they can be compared correctly. I used Australia/Hobart as that context and interpreted the stored booking times in the salon's zone. The server's location should not decide which appointment day the customer sees.

This also affected the meaning of today in the calendar and the exclusion of past slots. Comparing a local appointment against the wrong current date can produce a believable but incorrect calendar. I brought those comparisons into the business zone. The same principle applies to daily income: the owner's trading day needs to follow the salon's day, rather than an unrelated server boundary.

I used a named time zone instead of treating the difference as a fixed offset. Daylight-saving changes are part of the location's time rules. The useful change was not adding a time-zone label to the screen. It was using that interpretation where availability and daily figures are calculated, so the stored values and business rules refer to the same day and time.

Messages

A booking change needed to reach customers and staff

I repaired booking confirmations and added change and cancellation notices, including the cancellation reason. Staff alerts are part of the workflow too. A customer may see an updated dashboard, but staff still need to know that an appointment changed. I treated those messages as part of completing the action, because the business continues outside the customer screen.

I added appointment reminders for 24 hours and 2 hours before the booking. Each reminder tier can be configured for email, SMS, both or off. The purpose is to give the customer timely information about an appointment they already made. I can explain the schedule and the delivery behaviour. I do not attach a no-show reduction to it because I did not measure that result.

The important repair was how the scheduled work records completion. A reminder should not be marked sent simply because the scheduler tried it. I changed the path so a successful channel send is required before the reminder is recorded as sent. When sending fails, the reminder can be picked up on a later run. I also isolated channel failures so an email error does not prevent an SMS attempt.

That is a send outcome, rather than proof that a customer read a message. Keeping that distinction matters when explaining notification systems. The application can observe the result returned by its sending layer. It cannot infer attention from that result. I kept the case study claim at the behaviour implemented in the reminder workflow, rather than promise receipt or action by every customer.

Sending providers

I separated the booking message from the service that sends it

I built a provider layer for email and SMS, switchable through configuration. Booking logic decides which message needs to be sent. The provider layer handles the chosen delivery service. This keeps a provider decision from being repeated throughout the booking code. The business can change supported providers through configuration instead of changing each place that sends a confirmation or reminder.

There is extra work in supporting that boundary. Providers have different behaviour and configuration requirements. I accepted it because the alternative would tie ordinary booking actions directly to a particular sender. The useful result is a defined place to manage delivery differences. It is not a claim that switching providers requires no operational checks or that every provider behaves identically.

I also added SMS text normalisation and length-aware templates. Unusual characters can change how a message is encoded and how many billable segments it uses. Normalising the text and checking its length helps keep the message within the intended shape. I described this as a cost-control mechanism, rather than give a savings percentage that the project did not measure.

Email needed content repairs as well as sending logic. I added a plain-text part, image fallbacks and a working support link. These changes help the message remain useful when images do not appear or a recipient needs help. They also address delivery quality, but I would not describe template changes as a guarantee that a message will never reach a spam folder.

Speed

I reduced the mobile page from 17.2 MB to 1.7 MB

The customer website's mobile payload was 17.2 MB. I reduced it to 1.7 MB by changing the assets delivered to the page. I subset the icon font, served media suited to the screen size, converted images to a smaller format and removed unused assets. These were concrete reductions in what the browser had to download, rather than cosmetic changes to a loading indicator.

The icon font needed a guard around the subset so the page still had the icons it used. A smaller font is not a useful improvement if it removes symbols from the interface. Likewise, responsive media needed to preserve the content customers use to understand the salon and its services. The aim was to deliver the required page with less weight.

I added caching for the main home, services and pricing data, with invalidation when staff edit that content. The invalidation matters because the pages describe an operating business. A quick response with stale pricing would undermine the work on booking correctness. Asset caching and data caching solve different problems, and both need to respect how the content changes.

The payload comparison is the measured result I use here. It does not establish a conversion increase or a particular loading time for every phone. Network and device conditions vary. What changed is that the mobile page requires a much smaller download, alongside caching that avoids repeating the same server work for the main pages.

Before
17.2 MB
After
1.7 MB
Mobile page payload before and after the asset changes. Bar lengths use the measured sizes on the same scale.
Decisions

I repaired the working system and changed the parts that needed replacement

Should I replace the whole product?

Option

Start a complete replacement while carrying all existing behaviour into it.

Chosen

Repair the inherited backend, rebuild the customer website and separate the staff admin.

The salon already depended on bookings, so each part needed a decision based on its role in the operating business.

Which defects should come first?

Option

Choose the quickest visible changes from the list.

Chosen

Prioritise the consequences for the business, then work through booking correctness, communication and speed.

A booking system needs valid appointments and clear outcomes as well as a usable customer page.

Where should messaging providers be selected?

Option

Connect each booking action directly to a particular provider.

Chosen

Use a provider layer selected through configuration.

Delivery differences belong in a defined place, rather than across confirmations, changes and reminders.

What changed

The repairs reached the calendar, the messages and the page download

31 defects fixedThe documented repair work covered the inherited system and its booking workflows.
17.2 MB to 1.7 MBThe mobile page payload fell through asset changes, alongside caching for the main pages.
200 to 300 bookings a monthThe operating volume of the salon system I worked on, rather than a growth result attributed to the repairs.

Inherited a system that keeps breaking?

Tell me what is going wrong. We can start with the booking rules, messages and daily work your business depends on.

Let's talk