---
title: "Travel Search → Offer → Reprice → Booking Reference Architecture"
description: "Travel metasearch ve booking sistemlerinde search, canonical offer, reprice, payment ve booking akışını uçtan uca reference architecture olarak tasarlayın."
slug: "travel-search-offer-booking-reference-architecture"
translationKey: "architecture-travel-search-offer-booking-reference"
locale: "tr"
type: "guide"
category: "architecture"
tags: ["travel","search","offer","reprice","booking","architecture"]
publishedAt: "2026-09-27"
updatedAt: "2026-09-27"
reviewedAt: "2026-09-27"
technicalVerifiedAt: "2026-09-27"
codeExampleStatus: "illustrative"
---

Travel booking mimarisindeki kritik sınır **search sonucu ile book edilebilir offer'ın aynı şey olmadığını** kabul etmektir. Search, kullanıcıya seçenek üretir; reprice/availability check ise seçilen offer'ın halen geçerli olup olmadığını doğrular; booking ise provider tarafında yeni bir transaction yaratır.

Bu sayfa, hotel ve flight gibi farklı travel vertical'larında kullanılabilecek canonical bir omurga tanımlar.

## Reference architecture

```mermaid
%% title: Travel search to booking reference architecture
%% description: Search request'in supplier fan-out, normalization, offer selection, reprice, payment ve booking adımlarından geçişi.
flowchart LR
  A[Search Request] --> B[Canonical Search Context]
  B --> C[Supplier Eligibility]
  C --> D{Parallel Supplier Fan-out}
  D --> E[Supplier Adapter A]
  D --> F[Supplier Adapter B]
  E --> G[Normalize]
  F --> G
  G --> H[Property / Product Mapping]
  H --> I[Canonical Offers]
  I --> J[Ranking / Presentation]
  J --> K[Offer Selected]
  K --> L[Reprice / Availability Check]
  L --> M{Still valid?}
  M -->|No| N[Offer Changed / Expired]
  M -->|Yes| O[Booking Intent]
  O --> P[Payment Strategy]
  P --> Q[Provider Booking Create]
  Q --> R{Outcome}
  R -->|Confirmed| S[Booking Confirmed]
  R -->|Failed| T[Booking Failed]
  R -->|Unknown| U[Booking Unknown]
  U --> V[Lookup / Reconciliation]
  V --> S
  V --> T
```

## 1. Search context'i canonical yapın

Supplier request DTO'sunu domain modeliniz yapmayın. Önce ortak bir `SearchContext` üretin:

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

Adapter katmanı bu context'i provider-specific request'e çevirir. Böylece provider değiştirmek domain contract'ını bozmaz.

## 2. Search response ile canonical offer'ı ayırın

Her supplier farklı fiyat, tax, cancellation ve availability semantics'i taşır. Normalize edilmiş offer en az şu identity'leri korumalıdır:

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

Özellikle opaque token'ları kaybetmeyin. Search sırasında gelen bir booking token reprice veya booking call için zorunlu olabilir.

## 3. Offer immutable snapshot gibi davranmalı

UI'daki fiyatı daha sonra mutable bir row üzerinden güncellemek yerine seçilen offer'ın snapshot'ını tutun.

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

Böylece "kullanıcı hangi fiyatı gördü?", "reprice ne değiştirdi?" ve "hangi amount book edildi?" soruları cevaplanabilir.

## 4. Reprice ayrı bir domain adımıdır

Search sonucu doğrudan booking'e gitmemelidir. Reprice veya availability check şu değişiklikleri yakalamalıdır:

- fiyat değişti,
- tax/fee değişti,
- room/fare artık unavailable,
- cancellation policy değişti,
- payment model değişti,
- supplier token expire oldu,
- passenger/occupancy doğrulaması başarısız.

Reprice sonucu yeni bir `OfferVersion` üretmek, eski offer'ı overwrite etmekten daha güvenlidir.

## 5. Booking intent provider booking değildir

Kullanıcı "satın al" dediğinde önce internal bir `BookingIntent` oluşturun.

BookingIntent şunları bağlar:

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

Bu kayıt provider call başlamadan önce persist edilirse timeout durumunda recovery kolaylaşır.

## 6. Payment sequencing explicit olmalı

Tek bir doğru sıra yoktur. Provider ve commercial model'e göre:

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

uygulanabilir.

Bu nedenle PaymentState ve BookingState ayrı tutulmalıdır. "Payment success" booking confirmation değildir.

## 7. Booking create sonucu üçlüdür

Provider booking call için yalnız SUCCESS/FAILED kullanmayın:

- `CONFIRMED`
- `FAILED`
- `UNKNOWN`

Network timeout veya connection reset sonrası provider'ın booking oluşturup oluşturmadığı bilinmiyorsa durum UNKNOWN'dur. Otomatik create retry duplicate booking üretebilir.

## 8. UNKNOWN recovery

```mermaid
%% title: Unknown booking outcome recovery
%% description: Ambiguous booking sonucunda lookup ve reconciliation ile kesin booking state'ine ulaşılması.
stateDiagram-v2
  [*] --> BookingRequested
  BookingRequested --> Confirmed: provider confirms
  BookingRequested --> Failed: provider rejects
  BookingRequested --> Unknown: timeout / ambiguous transport failure
  Unknown --> Confirmed: lookup finds booking
  Unknown --> Failed: authoritative lookup finds no booking
  Unknown --> Unknown: evidence still inconclusive
```

Recovery kaynakları:

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

## 9. Canonical domain boundaries

Önerilen temel entity'ler:

| Entity | Sorumluluk |
|---|---|
| SearchContext | Kullanıcının canonical arama intent'i |
| SupplierExecution | Her provider çağrısının latency/outcome kaydı |
| CanonicalOffer | Normalize edilmiş search offer |
| OfferVersion | Search/reprice sonrası immutable offer snapshot |
| BookingIntent | Kullanıcı booking isteği ve idempotency sınırı |
| PaymentAttempt | Payment lifecycle |
| BookingAttempt | Supplier booking çağrısı |
| Booking | Materialized canonical booking state |
| BookingEvent | Immutable lifecycle evidence |
| ReconciliationRecord | Unknown/divergent state recovery kaydı |

## 10. Correlation zinciri

Her aşama birbirine bağlanabilmeli:

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

Provider request/response logları PII veya PCI data nedeniyle ham olarak sınırsız tutulmamalıdır; redaction ve retention politikası uygulanmalıdır.

## Failure modes

En önemli failure class'ları:

- stale search offer,
- reprice mismatch,
- duplicate provider booking,
- payment authorized fakat booking unknown,
- provider confirmed fakat local persistence başarısız,
- webhook gecikmesi veya kaybı,
- out-of-order lifecycle event,
- supplier partial outage,
- downstream timeout amplification,
- currency/tax normalization mismatch.

## Observability

Minimum ölçümler:

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

Trace üzerinde `searchId`, `bookingIntentId` ve `providerReference` aranabilir olmalıdır.

## Production checklist

- canonical SearchContext,
- immutable OfferVersion,
- mandatory reprice/availability gate,
- BookingIntent persistence before provider write,
- 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

Reference architecture'ın ana prensibi şudur:

**Provider DTO'larını değil, lifecycle sınırlarını canonicalize edin.**

Search, Offer, Reprice, Payment ve Booking birbirinden ayrı domain state'ler olarak modellendiğinde provider farklılıkları adapter katmanında kalır; retry, reconciliation ve troubleshooting ise ortak altyapı üzerinden yönetilebilir.
