Investigation deep dive

Someone else was holding our customer's passport.

A booking error nobody reported, five explanations that were wrong, and the test that found the real one: another booking site holding our customers' passport numbers before they'd paid.

The short version

Most leftfor good: the large majority of customers who hit this error never went on to book with us at all.
One countryheld the whole pattern: the rejections all lived on its routes, for one operator, week after week.
Every weekmore rejections. Customer service never saw one: customers who hit it just left.

When a customer books a ferry on our site, we first place a provisional booking with the ferry operator: a hold that reserves the places and checks the passenger details, confirmed once the customer pays. For one operator, on routes to and from one country, some of those holds came back rejected - the passenger's document number was "already in use" on that route.

Nobody had flagged it. It only showed up in the data.

Ruling things out

Five explanations that were wrong

When an outside system rejects your request, suspect your own request first. Each idea got the cheapest check that could rule it in or out.

  1. Bad passport numbersThey'd fail every time. Dozens of the failing numbers also appeared in successful bookings on the same routes.
  2. A mistranslated errorWe log the operator's full response. It said exactly "document number already used on this route".
  3. Clashing with ourselvesOne provisional request per attempt, no retries, and single-passenger bookings failed too, so there was nothing to collide with.
  4. Wrong document type for that countryPassports from that country were booking fine on the same routes every day.
  5. Random failureThe error only ever appeared on routes to and from that one country.

The clue

One customer who tried again

One customer hit the error, waited three minutes, and tried again with the same passengers on the same route. The second attempt worked.

So the passport wasn't the problem. Something had been holding it, and the hold had gone away, and it wasn't us: we'd only sent one request. Someone else was placing holds with our customers' passport numbers.

The obvious someone else is another booking site. Customers compare prices. If a rival site places a hold as soon as passenger details are entered, before payment, a customer who checks prices there and then comes to us gets rejected by the operator.

The test

I booked it myself

That idea could be tested directly. I went through a booking on another site, on one of the affected routes: entered passenger details, stopped before paying, then tried the same passengers on the same route with us.

  • The other site had already placed a hold with the operator at the passenger-details step, before any payment.
  • The hold lasted at least an hour.
  • Going back to the other site and trying again failed there too. Neither site could make the sale.
  • On a route outside that country, the other site held nothing early, matching our data exactly.

A customer compares prices, enters their details on two sites, and finds they can book on neither.

What was actually happening

One passport, two booking sites, one operator. Follow the request, the hold that blocks it, and the retry that exposed the cause.

31 seconds · no audio
The hold

The customer enters passport details on the other site. It reserves places with the operator before any payment.

Read the full sequence
  1. The hold. The customer enters passport details on the other site. It reserves places with the operator before any payment.
  2. Our site is rejected. The customer tries the same passport and route on our site. Our request reaches the operator, but the other site's hold is still there: document number already in use.
  3. The other site fails too. Going back to the other site and trying again also fails. Neither site can make the sale while the existing hold blocks a new request.
  4. The hold expires. The passport becomes available again. In the self-test, the hold lasted at least an hour; the clock here is compressed, not a measured countdown.
  5. One observed retry. One customer tried again with the same passengers and route, and got through after the other site's hold had expired.

What to do about it

A fix we can't make ourselves

The hold lives in the operator's system, so the real fix has to be theirs. I wrote up two options, and either solves it:

  • The latest hold wins. A new hold for the same passport on the same route replaces the older one. The site the customer is actually on gets the booking.
  • Holds expire sooner. Ten minutes is plenty to pay. An hour or more keeps a passport locked long after the customer has left.

On our side, a cheap stopgap is to tell the customer what's happening: these places may be held elsewhere, try again in a few minutes. It won't save everyone: in our data, almost none of the affected customers got through within the hour. Still, it beats an error and a lost customer.

What happened next: neither one. The operator didn't adopt either fix, and the retry message never shipped.

Wrapping up

What I'd do the same way again

A booking error that looked like bad data turned out to be another site's holds. The proof came from following the one customer whose retry worked, then booking through the other site myself.

Rule out your own system first, with the cheapest check that settles each idea. And when a pattern only makes sense from the customer's side, go and be the customer.

Glossary

Words used on this page

Hold
Places an operator reserves for a short time while a booking is finished.
Provisional booking
A booking placed with the operator before payment, confirmed once the customer pays.
Ferry operator
The company that runs the ferries and whose tickets we sell.
HARRY HIGGINS / FERRY BOOKING INVESTIGATION WRITE-UP

The next deep dive, in your inbox.