Travel technology··8 min read

One Hotel Supplier Timed Out. Why Did Your Entire Booking Platform Stop?

Three hotel suppliers receive the same search request. Two respond normally. The third stalls. A few seconds later, the traveler sees an error instead of results from the suppliers that were working.

That isn't only an upstream API problem. It is a hotel supplier API integration problem: one dependency was allowed to decide the outcome of the entire workflow.

Search failures are frustrating. Booking failures are more serious. When a reservation request times out, the booking might already exist, even though the platform never received its confirmation. What happens next decides whether the customer gets a reliable answer or a second reservation.

The useful engineering goal is not “never experience an API error.” It is to contain failures and preserve the correct business state when the information is incomplete.

Search failure and booking failure are not the same problem

A hotel search is a read. Depending on the product and on what the customer was promised, a platform can still be useful when one supplier is unavailable. A booking request changes the outside world: a room may be reserved, and a payment obligation may already exist.

These operations need different policies.

A failed call is not the same event in search and in booking. These are design choices for a booking platform, not a description of one product.
SituationAppropriate system behavior
SituationOne of three search suppliers times outAppropriate system behaviorReturn valid results from the others if business rules permit, and flag incomplete coverage
SituationAll search suppliers failAppropriate system behaviorExplain that the availability check couldn't be completed. Do not say the hotels are sold out
SituationA search rate token expiresAppropriate system behaviorRefresh availability or rate details under that supplier's workflow
SituationBooking response times outAppropriate system behaviorMark the status uncertain. Retrieve or reconcile the prior attempt before retrying
SituationBooking definitely rejectedAppropriate system behaviorPresent the confirmed failure, with safe recovery options

Treating every API error as “no availability” hides a supplier outage from operations and can mislead the traveler.

Stop a slow supplier from consuming the whole platform

A typical aggregator fans one request out to several external systems. Without isolation, a slow supplier can occupy shared worker threads, connection pools, or queues until the healthy suppliers degrade as well.

A more robust design sets a deadline, a concurrency limit, and health tracking for each supplier. The service can collect the results that finished inside an overall time budget, and it can say which suppliers did not finish.

The Microsoft bulkhead pattern describes isolated resource pools, so one component's failure does not exhaust resources the others need. Its circuit breaker pattern describes blocking calls that are likely to fail again, for a while, while still allowing a later check that the dependency has recovered. Those patterns solve different problems, and both need careful tuning. A circuit breaker protects the caller. It does not make a booking request idempotent.

An illustrative flow:

  • Supplier A responds in the allotted search window: include its valid offers.
  • Supplier B responds normally: include its valid offers.
  • Supplier C exceeds its deadline: record supplier_unavailable rather than no_rooms.
  • The aggregation layer returns the available results, with a clear internal note of what finished and what coverage is missing.

Whether customers should see partial results depends on what the booking product promises. That is a deliberate business decision, not an accident of whichever HTTP call finished first.

Illustrative architecture

One Supplier Down, Search Still Working

Same search requestFanned out in parallel. Each supplier has its own deadline and concurrency limit.

  1. Supplier AOwn limit

    Responds in the window. Valid offers included.

  2. Supplier BOwn limit

    Responds normally. Valid offers included.

  3. Supplier COwn limit, exceeded

    Timed out. Recorded as supplier_unavailable, not as no_rooms.

Results returned

Offers from A and B, with coverage marked incomplete because C did not answer.

Three supplier calls run in parallel, each inside its own limit. Two return offers. One times out. Search still returns the successful results and says the coverage is incomplete.

A booking API retry strategy cannot be “try again”

Expedia Rapid's error documentation warns that a booking timeout or a 5xx response does not necessarily invalidate a reservation. The failure may happen after the booking was created. Expedia documents retrieval with the original booking reference and related identifiers, so the eventual status can be established. That behavior is Expedia's, described in Expedia's Rapid docs.

Imagine this illustrative sequence:

  1. The application submits a booking request with a traceable attempt identifier.
  2. The supplier creates the reservation.
  3. The HTTP response is lost.
  4. The frontend reports a network error.
  5. The customer clicks Book again.

Without a controlled recovery path, that fifth step can repeat a real transaction. Whether a repeated request is safe depends on the supplier's documented idempotency contract and on whether that supplier can retrieve status. It does not depend on a UUID the backend generated. A locally generated identifier is not a supplier-side idempotency guarantee.

A timeout does not prove the booking failed. The right first action after an uncertain booking is usually to resolve the original attempt with the supplier's supported retrieval or reconciliation process, not to send the same mutation again.

Illustrative architecture

A Booking Exists but the Response Was Lost

  1. Submit the request

    The application sends a booking attempt with a traceable identifier.

  2. The supplier creates the reservation

    The room is reserved on the supplier side. That event has already happened.

  3. The response times out

    The HTTP acknowledgment never arrives. The reservation and the response are separate events.

  4. Retrieve the existing booking

    Look up the original attempt with the supplier's retrieval or reconciliation process.

  5. Confirm the result

    The status becomes known from that lookup, instead of from a second booking mutation.

The supplier can create the reservation and still fail to return the HTTP response. Recovery retrieves the booking that already exists and confirms its result. It does not send the mutation again on the assumption that the timeout meant failure.

Make transaction state explicit

Consider persisting a booking attempt before the external request is sent. A simplified application-level state machine could include:

requested → submitted → pending_resolution → confirmed | failed

Some applications also need cancellation-pending, amendment-pending, or manual-review. These are suggested design states. They are not a claim that every supplier exposes the same status model.

A state of pending_resolution is useful. It tells both the software and the support staff that the outcome is unknown, instead of filing the attempt as a rejected purchase.

A safe process also ties retries and recovery to the original identity, checks for an existing confirmation, records what the customer approved, and keeps payment and traveler details out of the logs.

AWS's guidance on making APIs idempotent explains why a recognized request identifier, and atomic handling of a duplicate mutation, matter. Those properties have to live in the API contract, or inside a transaction boundary you control. They cannot be assumed for every hotel supplier.

Normalize supplier data without hiding supplier differences

A canonical booking model simplifies the platform. Normalization is not permission to discard useful differences.

An adapter may convert room, board, and cancellation fields into a shared shape. It should still keep the original identifiers, the policy text, the diagnostic codes, and the correlation references, so a disputed booking can be traced to its source.

One API may return a structured JSON business error. Another layer may return an HTML page from a gateway. Expedia's error reference notes that unexpected response formats can occur. A parser that assumes every error is JSON with a message field can crash at the moment the platform most needs to fail gently.

Validate the response format defensively, classify what you do not recognize, and keep enough diagnostic provenance to investigate. Redact payment and traveler information before it reaches a log.

Monitor business uncertainty, not only HTTP uptime

A green infrastructure dashboard does not mean customers have confirmed bookings. Useful measures include:

  • Search completion by supplier and by operation.
  • Response latency and timeout rates inside the user's time budget.
  • Rate and parsing failures by supplier and rate plan.
  • Booking attempts sitting in an unresolved state, and how old they are.
  • Reconciliation success, and the time it takes to resolve them.
  • Duplicate-detection events and support escalations.

For reads that are safe to retry, use a bounded number of retries, with backoff and jitter where that fits. AWS Well-Architected says to control retry traffic. Unbounded retries can make an incident worse. The same “try again” habit does not belong on a booking mutation.

Resilience is what the system does after the happy path breaks

A booking platform does not become reliable by assuming every supplier is reliable. It becomes reliable by isolating dependencies, preserving what an offer means, telling an uncertain status apart from a confirmed failure, and giving operators a clear route to recovery.

If a single supplier outage regularly takes search down, or if a booking timeout leads people to retry a mutation by hand, review failure isolation and reservation-state recovery before adding another integration.

WebbingHUB Travel works in supplier connectivity and booking workflows. The useful start is one real exception the team cannot resolve.

Sources and further reading