Travel Search → Offer → Reprice → Booking Reference Architecture

Design an end-to-end reference architecture for travel search, canonical offers, repricing, payment and booking across supplier integrations.

Editorial information
Advertisement

The critical boundary in travel booking architecture is recognizing that a search result is not the same thing as a bookable offer. Search produces options, reprice or availability check verifies that the selected option is still valid, and booking creates a new transaction at the supplier.

This page defines a canonical backbone that can be reused across travel verticals such as hotels and flights.

Reference architecture

Travel search to booking reference architectureTravel search to booking reference architecture

Mermaid source (.mmd)

1. Canonicalize the search context

Do not turn a supplier request DTO into your domain model. Create a shared SearchContext first:

json
{
  "searchId": "srch_123",
  "vertical": "hotel",
  "market": "TR",
  "currency": "TRY",
  "checkIn": "2026-10-10",
  "checkOut": "2026-10-12",
  "occupancies": [
    { "adults": 2, "childrenAges": [] }
  ]
}

Each adapter translates that context into a provider-specific request. Supplier changes then stay outside the domain contract.

2. Separate search responses from canonical offers

Suppliers expose different price, tax, cancellation and availability semantics. A normalized offer should preserve at least:

  • internal offer ID,
  • supplier ID,
  • supplier offer/rate ID,
  • property/product reference,
  • total price and currency,
  • tax/fee breakdown,
  • cancellation/refund policy,
  • payment timing,
  • room/fare/product attributes,
  • availability/freshness timestamp,
  • raw provider context or opaque booking token.

Do not lose opaque tokens. A token returned during search may be mandatory for repricing or booking.

3. Treat an offer as an immutable snapshot

Instead of mutating the price later on one database row, preserve snapshots:

text
SearchOffer
  -> SelectedOfferSnapshot
  -> RepricedOffer
  -> BookingIntent
  -> ProviderBooking

This makes it possible to answer: what did the traveler see, what changed at reprice, and what amount was actually booked?

4. Reprice is a separate domain step

A search result should not move directly to booking. Reprice or availability check should detect:

  • price changes,
  • tax/fee changes,
  • room/fare no longer available,
  • cancellation-policy changes,
  • payment-model changes,
  • expired supplier tokens,
  • passenger/occupancy validation failures.

Creating a new OfferVersion is safer than overwriting the original search offer.

5. Booking intent is not a provider booking

When the traveler clicks purchase, create an internal BookingIntent before calling the supplier.

It should bind:

  • selected/repriced offer,
  • traveler/passenger data,
  • payment strategy,
  • idempotency key,
  • correlation ID,
  • consent/terms version,
  • client/session context.

Persisting this boundary before the external call makes timeout recovery much easier.

6. Make payment sequencing explicit

There is no single correct sequence. Depending on the supplier and commercial model, systems may use:

text
authorize -> book -> capture
book -> authorize/capture
pay at property
virtual card / settlement later

Keep PaymentState and BookingState separate. A successful payment is not proof of a confirmed booking.

7. Model three booking outcomes

Do not reduce a provider booking call to SUCCESS/FAILED:

  • CONFIRMED
  • FAILED
  • UNKNOWN

After a network timeout or connection reset, the supplier may still have created the booking. Retrying create blindly can produce a duplicate reservation.

8. Recover UNKNOWN outcomes

Unknown booking outcome recoveryUnknown booking outcome recovery

Mermaid source (.mmd)

Useful recovery evidence includes:

  • provider booking lookup,
  • client reference / idempotency-key lookup,
  • webhook/event delivery,
  • scheduled reconciliation,
  • manual operations queue.

9. Canonical domain boundaries

EntityResponsibility
SearchContextCanonical traveler search intent
SupplierExecutionLatency/outcome of each provider call
CanonicalOfferNormalized search offer
OfferVersionImmutable search/reprice snapshot
BookingIntentUser booking intent and idempotency boundary
PaymentAttemptPayment lifecycle
BookingAttemptSupplier booking call
BookingMaterialized canonical booking state
BookingEventImmutable lifecycle evidence
ReconciliationRecordRecovery for unknown/divergent state

10. Preserve the correlation chain

Every stage should be traceable:

text
searchId
 -> offerId / offerVersion
 -> bookingIntentId
 -> paymentAttemptId
 -> bookingAttemptId
 -> providerReference
 -> bookingId

Raw provider request/response logs must not be retained without limits when they contain PII or payment data. Apply redaction and retention rules.

Failure modes

Important failure classes include:

  • stale search offer,
  • reprice mismatch,
  • duplicate provider booking,
  • payment authorized while booking remains unknown,
  • provider confirmed but local persistence failed,
  • delayed or lost webhook,
  • out-of-order lifecycle events,
  • supplier partial outage,
  • timeout amplification,
  • currency/tax normalization mismatch.

Observability

Track at minimum:

  • search success rate,
  • supplier p50/p95/p99 latency,
  • search-to-offer-selection conversion,
  • reprice success/mismatch rate,
  • booking confirmation rate,
  • booking UNKNOWN rate,
  • duplicate-prevention hits,
  • reconciliation age,
  • payment/booking divergence,
  • end-to-end search-to-confirmed-booking latency.

searchId, bookingIntentId and providerReference should be searchable in traces and operational tooling.

Production checklist

  • canonical SearchContext,
  • immutable OfferVersion,
  • mandatory reprice/availability gate,
  • persist BookingIntent before provider writes,
  • explicit payment sequencing,
  • CONFIRMED / FAILED / UNKNOWN booking outcomes,
  • reconciliation path,
  • operation-scoped idempotency,
  • end-to-end correlation IDs,
  • PII-safe logging and retention.

Design rule

The main principle is:

Canonicalize lifecycle boundaries, not provider DTOs.

When Search, Offer, Reprice, Payment and Booking are modeled as separate domain states, supplier differences stay inside adapters while retry, reconciliation and troubleshooting can share a common architecture.

Technical advisory

Let’s review your architecture.

We can assess your travel distribution and metasearch architecture for scalability, failure modes and operations.

Discuss your project →

Related content