Skip to content
Ironflow is pre-1.0: APIs can change between releases. Pin a version. What is ready →

Bookings and reservations

A traveler books a flight and hotel as one trip. Both reservations must succeed before your application confirms the trip. If one fails, the customer needs a clear outcome and completed holds need a release path. The same shape fits appointment slots, event seats, and rental equipment.

Your application owns availability rules, hold deadlines, provider integrations, and confirmation policy. Ironflow coordinates durable work and can store the reservation facts that your own service uses to enforce those rules.

Validate the booking request and check availability. Reserve each resource in a durable step, saving the returned reservation identifier. Register release actions where the provider and business policy support them. Confirm payment and the trip when every required reservation has succeeded.

For application-owned inventory, read a resource’s entity stream and append the reservation with its expected version. For outside providers, use their reservation and idempotency contracts. A provider’s authoritative inventory cannot be protected solely by a version check on your local stream.

Two requests compete for the last application-owned seat. Both read the same availability version. A guarded append lets one proceed and rejects the other with a conflict. Your application re-evaluates availability and tells the losing request that the resource is gone.

Another failure happens when the flight succeeds and the hotel is unavailable. A terminal failure, such as a NonRetryableError, runs the registered releases in reverse order. A retryable failure is retried first; under the default pause policy, an exhausted retry pauses the run instead of releasing holds. An unfinished release can repeat after interruption, so the provider action must be idempotent. Decide separately how user cancellation releases existing holds.

Durable steps preserve completed reservation results. Entity-stream version checks support optimistic concurrency for the state your application owns. Compensation handles registered undo actions on non-retryable failures. Events and projections can supply availability and booking-status views.

Hold expiry is an application workflow you can add with durable sleeps or deadline events. Expiry and confirmation can race; recheck the authoritative reservation state before committing either transition. Your reducer and version checks enforce the business rule that a hold cannot be both released and confirmed.

This is an illustrative flow:

  1. Validate the trip and identify the required resources.
  2. Reserve each resource with the relevant concurrency/idempotency contract.
  3. Save reservation IDs and register release actions.
  4. Confirm the booking or compensate after a terminal failure.
  5. Add an expiry path that checks the current hold state before release.
  6. Derive availability and booking views from recorded domain events.
  • The travel booking example holds a seat and a room, charges the card, and releases both holds in reverse when the card is declined. Its seat holds use expected-version appends on the flight’s inventory stream.
  • Sagas and compensation explains the reservation-and-release execution pattern and its failure conditions.
  • Entity streams demonstrates expected-version checks for competing updates.
  • Step primitives covers durable sleeps and event waits for an application-defined hold-expiry extension.