Payment + Booking Distributed Transaction

Model payment and supplier booking as a distributed transaction using authorization, capture, compensation, UNKNOWN outcomes and reconciliation.

Editorial information
Advertisement

A payment gateway and a supplier booking API do not participate in one ACID transaction. Travel systems therefore need to model booking + payment as a distributed transaction, with success, failure and unknown outcomes handled independently for every external step.

The core problem

Two outcomes need to line up:

  1. the traveler payment obligation,
  2. the supplier reservation.

They happen in different systems, so intermediate divergence is normal:

  • payment authorized, booking failed,
  • booking confirmed, capture failed,
  • payment timeout with unknown outcome,
  • booking timeout with unknown outcome,
  • cancellation succeeded but refund failed,
  • refund succeeded while local booking state stayed stale.

There is no single transaction

Payment and booking distributed transactionPayment and booking distributed transaction

Mermaid source (.mmd)

Why authorize → book → capture?

In many models, authorizing first and capturing only after booking confirmation reduces risk:

  • the traveler is not fully charged when no booking exists,
  • a failed booking can be followed by an authorization void.

This is not universal. Some suppliers or commercial models require full capture, pay-at-property, or virtual-card settlement.

Other sequencing models

Book → pay

Create the reservation first, then collect payment.

Risk: a payment failure may require cancelling an already-confirmed booking.

Pay/capture → book

Finalize payment before the reservation.

Risk: if booking fails, the system must compensate with a refund or void.

Pay at property

The platform may not orchestrate the payment, but booking state and payment liability still need separate modeling.

Canonical transaction state

Do not use one transaction_status. Keep separate state machines:

text
PaymentState:
CREATED -> AUTHORIZING -> AUTHORIZED -> CAPTURING -> CAPTURED
                        -> FAILED
                        -> UNKNOWN
                        -> VOIDED
                        -> REFUNDED

BookingState:
REQUESTED -> CONFIRMED
          -> FAILED
          -> UNKNOWN
          -> CANCELLED

An orchestration state can sit above them:

text
BookingTransaction:
STARTED
PAYMENT_READY
BOOKING_PENDING
BOOKING_CONFIRMED
PAYMENT_FINALIZING
COMPLETED
RECOVERY_REQUIRED
COMPENSATING
FAILED

Saga pattern

Distributed work cannot be rolled back like one database transaction, so use compensation.

Travel booking compensation sagaTravel booking compensation saga

Mermaid source (.mmd)

Compensation is not a true rollback. Supplier cancellation fees or payment costs may already exist.

UNKNOWN outcomes can happen on both sides

Booking UNKNOWN

The supplier request times out. Do not blindly repeat create; perform lookup and reconciliation.

Payment UNKNOWN

The gateway times out. Starting a new payment transaction can double-charge the traveler. Use the provider's idempotency or status-lookup mechanism.

Idempotency boundaries

Use a distinct key per semantic operation:

  • booking create idempotency key,
  • payment authorization key,
  • capture key,
  • cancellation key,
  • refund key.

Do not reuse one key across different operations.

Transaction log

The orchestrator should retain immutable attempt history as well as current state.

json
{
  "bookingIntentId": "bi_123",
  "operation": "BOOK",
  "attempt": 1,
  "idempotencyKey": "book_bi_123_v1",
  "status": "UNKNOWN",
  "providerReference": null,
  "startedAt": "2026-09-27T10:00:00Z"
}

Recovery policy

SituationFirst action
Payment authorization UNKNOWNprovider lookup / idempotent status query
Booking create UNKNOWNbooking lookup / reconciliation
Booking FAILED + payment AUTHORIZEDvoid authorization
Booking CONFIRMED + capture FAILEDcapture recovery; cancel if policy requires
Cancellation CONFIRMED + refund FAILEDretry/reconcile refund
Refund UNKNOWNpayment lookup; no blind retry

Outbox for local consistency

A supplier may confirm the booking while local event publication fails. Use a transactional outbox:

text
local transaction:
  update booking state
  insert outbox event
commit

background publisher:
  publish outbox event
  mark published

This does not make the external booking call ACID. It only improves consistency between local state and event publication.

Retry policy

Retry should not happen simply because an error looks technical.

A safe retry requires:

  • idempotent semantics or provider idempotency support,
  • known outcome of the previous attempt,
  • exponential backoff with jitter,
  • bounded retry budget,
  • rate-limit awareness.

Booking create without idempotency is one of the most dangerous operations to retry.

Reconciliation worker

Continuously inspect records such as:

  • long-lived UNKNOWN booking,
  • AUTHORIZED payment with no terminal booking,
  • CONFIRMED booking with incomplete payment,
  • CANCELLED booking with incomplete refund,
  • local/provider state mismatch.

Fetch authoritative provider evidence and repair canonical state.

Manual operations queue

Some divergence needs human review. An operations queue should show:

  • traveler-safe booking summary,
  • provider reference,
  • payment reference,
  • current booking/payment states,
  • attempt history,
  • suggested next action,
  • risk indicators such as duplicate charge, duplicate booking or cancellation fee.

Failure modes

  • booking confirmed while capture fails,
  • payment captured while booking is FAILED/UNKNOWN,
  • compensation itself timing out,
  • duplicate capture/refund retries,
  • local outbox/state diverging from provider state,
  • manual operations creating a second booking or refund.

Observability

Track:

  • authorization success rate,
  • booking confirmation rate,
  • capture success rate,
  • compensation rate,
  • void/refund latency,
  • booking UNKNOWN rate,
  • payment UNKNOWN rate,
  • booking-payment divergence count,
  • reconciliation age,
  • manual-intervention rate,
  • duplicate-prevention hits.

Production checklist

  • separate payment and booking state machines,
  • choose sequencing explicitly per provider/commercial contract,
  • use idempotency keys for every write operation,
  • model UNKNOWN as a first-class state,
  • define compensation policy,
  • provide reconciliation workers and manual operations queues,
  • use a transactional outbox for local state/event consistency.

Design principle

Payment and Booking are separate state machines; orchestration coordinates them.

Keeping intent, attempt, evidence and compensation explicit makes timeouts and partial failures manageable instead of hiding them inside one status field.

Technical advisory

Planning a similar integration?

We can review requirements, feed/API design and the production approach with you.

Discuss your project →

Related content

architecture

Agentic Travel Transaction Safety

Prevent duplicate booking and payment caused by agent loops, retries and tool invocation using idempotency, side-effect guards and UNKNOWN-aware recovery.

agentic-travelidempotencyduplicate-transaction
Explore →
architecture

Travel Booking Saga and Compensation Patterns

Design Saga and compensation patterns for travel booking, payment, cancellation and refund workflows where rollback is impossible.

sagacompensationbooking
Explore →
distribution-api

Hotelbeds API Suite: Bedbank Distribution Profile

developer.hotelbeds.com

A technical profile of the HBX Group Hotelbeds API Suite covering hotel booking, content and cache APIs for B2B accommodation distribution.

hotelbedshbxbedbank
Explore →
distribution

OTA vs Metasearch vs Travel Marketplace: Key Differences

Compare OTA, metasearch and travel-marketplace models by transaction ownership, supplier relationships, monetization, handoff and technical architecture.

otametasearchtravel-marketplace
Explore →
distribution

Package Holiday vs Hotel Metasearch: Architecture Differences

Compare package-holiday distribution with hotel metasearch by offer identity, pricing, supplier topology, booking ownership and cancellation.

package-holidayhotel-metasearchtour-operator
Explore →
distribution-api

Sabre Travel APIs: GDS and Travel Distribution Profile

developer.sabre.com

A technical profile of Sabre Travel APIs covering air, lodging, car, booking and agency workflows across a GDS-oriented B2B platform.

sabregdsflight-api
Explore →