Home

Availability Controls: O&D, Nesting, and Married Segments

March 20, 2024 • ~20 min read

Inventory Revenue Mgmt Optimization Implementation

1. Introduction & Problem Framing

Availability control decides whether a request for seats in a given fare product can be accepted right now. Poor control leaks revenue (selling cheap seats on high value itineraries) or destroys conversion (over‑protecting inventory). For engineers, the challenge is translating revenue management (RM) output (forecasts, bid prices, protection levels) into deterministic APIs used by search and booking flows, while handling multi‑segment journeys where value is itinerary dependent.

Key tension: The seat is physical per leg, but value is per Origin & Destination (O&D) itinerary. O&D control resolves this by optimizing over displacement value of alternatives.

2. Core Mental Model

Three layers supply the answer “how many seats are open in booking class X for itinerary Y?”

  1. Physical Inventory: Remaining seats by flight leg (A–B, B–C).
  2. Control Mechanism: Protection levels or bid prices derived from demand forecasting & optimization (e.g., EMSR, dynamic programming, network RM).
  3. Translation Layer: Business rules (married segments, nesting, blackout overrides) applied to produce booking class availability (0–9 / RBD counts) or structured Offer limits.

3. O&D Control Fundamentals

Network vs Leg Control: Leg control opens classes solely based on leg forecast. O&D (network) control considers displacement: selling a seat A–B now might block a higher yield A–C passenger connecting through B later.

  • Market (O&D): Origin + Destination + (sometimes cabin, channel) with forecasted demand by fare product.
  • Feasible Itineraries: Each O&D demand bucket maps to one or more leg paths.
  • Displacement Cost: Opportunity cost of consuming seat capacity now vs alternative future sale on overlapping legs.

Two mainstream implementations:

  • Protection Level Methods: Compute protection (e.g., keep 12 seats for high yield O&D) then convert to open seats per lower buckets using nesting logic.
  • Bid Price Control: Assign a shadow price per leg; an itinerary accepted if its offered fare ≥ sum(bid prices of legs). Network yield management often computes bid prices via linear programming approximations.

4. Nesting Strategies (Classical & Modern)

Nesting defines hierarchical access of fare classes to shared seat inventory.

TypeDescriptionProsCons / Risks
Traditional Classical NestingOrdered fare classes (Y highest → deep discount). Lower class opens only if all protected higher-demand seats satisfied.Simplicity, easy to communicateOver-protection if forecast variance high
Virtual Nesting (Buckets)Map fare products into aggregated value bands (virtual classes) rather than one-to-one with RBD.Fewer control variables, dampens noiseLoss of granularity for micro-yield segments
Hybrid / Dynamic NestingPeriodically reassign fare products to nests based on updated bid values.Adapts to demand shiftsComplex; requires atomic updates to avoid flicker
Open Pricing / ContinuousRather than discrete nests, dynamic price presented with availability gating still referencing minimum acceptance thresholds.Revenue uplift via finer granularityHarder explainability & auditing; bridging legacy systems

Implementation Note: Maintain an immutable snapshot: fareProduct → nestID → protectionLevelVersion. Pricing and availability queries must reference the same version (or detect mismatch).

5. Bid Prices & Displacement Logic

Bid price: Shadow (opportunity) cost of selling one more seat on that leg at that time. Acceptance rule (for itinerary with price P across legs L):

Accept if:   P >= Σ (bidPrice[leg])
Else reject / close lower classes

Network control computes bid prices so that if you accept an itinerary, you expect non-negative incremental contribution vs keeping the seat for potential future higher-value demand.

Edge Cases: Bid price monotonicity across time-bands and cabins may need smoothing (avoid oscillating open/close states). Implement post-processing smoothing (e.g., moving average or convexity constraint) after raw optimization output.

6. Married Segments Logic

Married segments enforce joint availability of multiple legs used together to prevent re-pricing or rebooking passengers at unintended values.

  • Purpose: Stop “gaming” where a customer books A–B–C (open) then drops B–C to hold a scarce A–B seat that was closed standalone.
  • Mechanism: Host stores binding between segments; cancellation or change triggers revalidation; partial cancellation disallowed or forces reprice.
  • Data Structure: A marriage group ID pointing to list of segment keys. Status states: ACTIVE, BROKEN (requires reprice), RELEASED (after flown/void).
  • Offer Layer: When constructing offers, annotate itinerary segments with marriageGroup tokens so downstream servicing logic can enforce constraints.

Implementation Tip: Expose an idempotent API to validate married segment integrity prior to ticketing and again during changes. Caching stale marriages is a common failure source.

7. Availability Calculation Pipeline

Input: O&D request (A->C), travel date(s), cabin, constraints (max connects)

1. Enumerate feasible itineraries (A-B-C, A-C nonstop if exists).
2. Fetch leg inventory snapshots (A-B flight X, B-C flight Y).
3. Load control artifacts:
   - Nest definitions & protection levels (or)
   - Bid prices per leg time-slice
4. For each itinerary:
   a. Compute controlling value threshold (sum bid prices).
   b. Determine candidate fare products / RBD mapping.
   c. Evaluate open condition:
        (FareAmount >= threshold) AND (remainingPhysicalSeats > 0)
   d. Apply married segment constraints (if multi-leg).
   e. Apply blackout / channel overrides.
5. Produce availability vector:
   - Per RBD: integer 0..maxDisplay (often capped at 9)
   - Or priced offer list (for dynamic).
6. Attach provenance:
   - InventorySnapshotVersion
   - ControlVersion (bid price or protection timestamp)
   - EvaluationTimestamp
7. Optionally pre-reserve (soft block) if hold logic required.

Fast Path Optimization: For large shopping queries, compress evaluation by grouping itineraries with identical leg sets and control thresholds to reuse computed open/close states.

8. Internal Data Model & Keys

LegKey = flightNumber + departureDate + boardPoint + offPoint
InventorySnapshot {
  legKey -> { cabin: { RBD: { seatsRemaining, lastUpdate } } }
}

ControlVersion { id, generatedAt, method: 'BID_PRICE' | 'PROTECTION', smoothingParams }

BidPriceTable {
  controlVersionId,
  legKey -> { bidPriceCurrency, bidPriceValue }
}

ProtectionLevels {
  controlVersionId,
  legKey -> [ { nestId, protectSeats } ordered high->low ]
}

FareProduct {
  id, fareBasis, cabin, bookingClass, anchorPrice, market O&D, brandId, channelPolicy
  mapping: { bookingClass -> nestId }
}

MarriageGroup {
  groupId, segmentLegKeys[], status, createdAt, version
}

AvailabilityResult {
  requestId, od, itineraries:[
     { segmentLegKeys[], marriageGroupCandidate?, rbdAvailability:{ RBD: count },
       provenance:{ inventoryVersion, controlVersionId, evalAt } }
  ]
}

9. Worked Micro Examples

9.1 Protection Level Nesting Example

Physical seats on Leg A-B: 20
Protection (high->low):
  Nest H (Full Y): protect 5
  Nest M: protect 8 (cumulative 13)
  Nest L: protect 16 (cumulative 16)
Open seats logic for discount nest D:
  Remaining seats = 20
  Cumulative protection above D = 16
  Open seats for D = max(0, 20 - 16) = 4
Display cap (9) -> show '4' (or '4' truncated if >9)

9.2 Bid Price Acceptance

Leg A-B bidPrice = 70
Leg B-C bidPrice = 60
Itinerary A-B-C proposed fare: 115
Threshold = 70 + 60 = 130
115 < 130 => Reject / close low RBDs
If dynamic engine can adjust: raise fare to >=130 or suppress itinerary.

9.3 Married Segment Enforcement

Booking: A-B-C (group G123). Later passenger attempts change:
  Remove B-C only.
System:
  Validate group G123: segment removal breaks marriage.
  Reprice A-B alone -> A-B single-leg fare may be higher or closed.
  If accepted: create new booking for A-B, retire group G123, charge difference.

10. Dilution & Protection Failures

Dilution: Selling a seat at a lower net contribution than an alternative expected demand would have provided. Drivers:

  • Lag in applying tightened bid prices after demand spike.
  • Incorrect mapping of fare product to nest (misconfigured brand upgrade paths).
  • Married segment bypass via partial cancellations not revalidated.

Detection Metric: Post-hoc compare realized average yield per leg vs forecast conditional yield distribution; deviation beyond tolerance triggers recalibration or anomaly alert.

11. Interaction with Pricing & Shopping

  • Availability First vs Joint Offer: Legacy flows price only itineraries with open RBDs. Modern offer engines evaluate willingness-to-pay + adjust price; availability becomes a gating constraint, not a discrete step.
  • Synchronization: Pricing must treat availability snapshot as ephemeral: revalidate at commit to avoid oversell especially near departure (tight load factor).
  • Class of Service vs Brand: Brand bundles may map multiple fare products to same RBD; open RBD but restrict brand if brand-level inventory logic (rare) or channel policy forbids.

12. Caching & Distribution Considerations

Volatility: Availability changes frequently (bookings, cancellations, RM updates). Cache invalidation must be sub-minute for critical O&Ds in peak booking horizon.

  • Key Design: Cache by (LegKey, ControlVersion) with TTL plus invalidation events (booking commit, cancellation, RM update).
  • Negative Caching: Avoid heavy negative caching (closed classes) beyond very short TTL to prevent stale closures.
  • Partial Warm: Pre-warm high traffic O&Ds for next 24h departure windows; lazy load long-tail after first request.

Edge Strategy: For global distribution, replicate control artifacts (bid prices) to edge POPs; keep write path (booking commit) routed to central authority to perform atomic seat decrement and push diff events outward.

13. Common Failure Modes & Diagnostics

FailureSymptomLikely Root CauseMitigation
Phantom AvailabilityItinerary appears bookable; fails at commitStale cache; marriage revalidation failure; race between hold and decrementShort-lived availability tokens; commit-time host recheck
Dilution SpikeYield per seat drops vs forecast bandMissed bid price update; mis-nesting after RM file ingest errorAutomated control version completeness check & fallback
Oscillating Open/CloseRepeated class flicker within minutesUn-smoothed bid price noise or demand forecast jitterSmoothing algorithm; minimum hold window for state transitions
Married Segment AbuseHigh-yield seats vanish w/ unusual cancellationsMissing integrity check on partial cancelTrigger reprice workflow; audit logs & anomaly detection
Oversell (Above Target)Leg load factor > planned oversell toleranceParallel booking race; control artifact lag > thresholdAtomic decrement service; sequence number gating

14. Observability & KPIs

  • Control Latency: Time from RM output generation → availability service adoption (p50/p95).
  • Cache Staleness: Age distribution of inventory snapshots served.
  • Flicker Rate: Count of open/close toggles per class per hour (threshold alert).
  • Dilution Index: Realized yield / expected yield (weighted) by departure bucket (e.g., 0–7 days, 8–21 days).
  • Commit Mismatch Rate: Proportion of search responses failing commit due to availability change.
  • Married Integrity Violations: Attempted partial cancellation requiring reprice vs total bookings.

15. Engineering Patterns & Algorithms

15.1 Atomic Inventory Service

POST /reserve
Body: { itineraryId, legSegments:[{legKey, rbd, seats:1}], requestId }
Process:
  1. Validate seatsRemaining >= requested for each leg+rbd
  2. Decrement atomically (optimistic CAS with version)
  3. Emit event INVENTORY_RESERVED {requestId, versionAfter}
  4. TTL hold; confirm (ticket) or release

15.2 Bid Price Evaluation

function isOpen(itinerary, fareAmount, controlVersion):
   threshold = sum(bidPrice[legKey])
   return fareAmount >= threshold

15.3 Nest Resolution

function seatsOpenForClass(leg, class):
  pl = cumulativeProtectionAbove(class)
  return max(0, physicalSeats - pl)

15.4 Version Fencing

Attach controlVersionId to availability result; booking commit must either accept if currentVersion == responseVersion OR re-evaluate if changed.

15.5 State Smoothing

// Keep open state at least MIN_WINDOW unless severe threshold violation
if (proposedState != currentState && timeSinceChange < MIN_WINDOW)
   retain currentState
else
   apply proposedState

16. Test Strategy & Synthetic Scenarios

  • Determinism Suite: Same inputs (inventory snapshot + control version) must produce identical availability vector hash.
  • Race Simulation: Concurrent holds over final seats ensure exactly one success; others fail gracefully.
  • Bid Price Boundary: Fare exactly equal to threshold accepted; just below rejected (off-by-one guard).
  • Married Segment Break: Remove subset segment; verify reprice call mandatory.
  • Forecast Shock: Inject demand spike; ensure control adoption time within SLA.
  • Nesting Remap: Change fare→nest mapping mid-day; confirm snapshot isolation (old searches not misinterpreted).

17. Modernization Toward Offers & Orders

As the industry migrates to offers & orders, availability logic moves closer to dynamic offer construction:

  • Offer Eligibility Service: Instead of publishing raw RBD counts, provide an API that evaluates itinerary + desired product attributes → decision (ACCEPT with price range / REJECT).
  • Continuous Pricing Integration: After availability gating, algorithm produces a context-adjusted price anchored by displacement cost; record anchorThreshold (sum bid prices) and marginAdd.
  • Servicing Continuity: Orders store both accepted threshold and inventory version so changes can be evaluated against historical context.
  • Interline / Alliance: Transitional phase requires exposing classical RBD indicators for partners still on legacy messaging while internally using higher-resolution controls.

18. Implementation Checklist

  • Define canonical LegKey and InventorySnapshot versioning.
  • Implement both protection-level and bid price evaluation paths (feature flag) for incremental rollout.
  • Store immutable mapping of fareProduct → nestId per controlVersion.
  • Ensure atomic decrement API with idempotency key (requestId).
  • Attach controlVersionId & inventoryVersion to every availability response.
  • Provide trace object: itinerary, decision path, thresholds, timing.
  • Smoothing layer to reduce oscillation; telemetry of flicker rate.
  • Married segment integrity endpoint for pre-ticket, reissue, cancel flows.
  • Alerting on dilution index deviation and commit mismatch rate.
  • Chaos test: delayed RM feed ingestion → verify fallback to last stable version.
  • Security: rate limit reservation/hold operations to prevent seat denial attacks.

19. Mini Glossary

  • O&D Control: Managing availability using network displacement value rather than independent leg controls.
  • Nesting: Hierarchical allocation of seats to fare classes via protection levels.
  • Bid Price: Shadow value threshold used to accept or reject an itinerary sale.
  • Displacement Cost: Lost expected future revenue from selling a seat now.
  • Married Segments: Binding of multiple flight segments requiring joint handling.
  • Dilution: Revenue loss from selling below displacement-optimal level.
  • Protection Level: Quantity of seats reserved for higher-value demand segments.

20. Sources & Further Reading

Conceptual, non-proprietary references used for framing (specific proprietary algorithms and data feeds intentionally not reproduced):

  • Academic literature on airline network revenue management (bid price control, EMSR variants).
  • Public conference presentations (AGIFORS, PODS) discussing O&D control adoption challenges.
  • Industry articles on married segment logic & inventory integrity.
  • Open explanations of seat inventory nesting and demand forecasting principles.

Consult licensed RM vendor / airline internal documentation for proprietary parameterization and optimization formulations.

21. Disclaimer

This article outlines widely understood industry concepts for engineering enablement. It deliberately omits proprietary RM vendor algorithms, optimization coefficients, and confidential data schemas. Validate all implementation details against your airline’s contractual RM system documentation, regulatory obligations (consumer disclosure, competition law), and internal revenue accounting policies.

Back to all blogs