Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,130 | Comments: 45,558

filter by tags archive

Modeling exerciseFlights & Travelers

time to read 5 min | 857 words

I just got a really interesting customer inquiry, and I got their approval to share it. The basic problem is booking flights, and how to handle that.

The customer suggested something like the following:

{   //customers/12345
    "Name" : "John Doe",
    "Bookings" : [{
        "FlightId": "flights/1234",
        "BookingId": "1asifyupi",
        "Flight": "EA-4814",
        "From": "Iceland",
        "To" : "Japan", 
        "DateBooked" : "2012/1/1"

{ // flight/1234
   "PlaneId": "planes/1234"// centralized miles flown, service history
           "Seat": "F16"
           "BookedBy": "1asifyupi"

But that is probably a… suboptimal way to handle this. Let us go over the type of entities that we have here:

  • Customers / Passengers
  • Flights
  • Planes
  • Booking

The key point in here is that each of those is pretty independent. Note that for simplicity’s sake, I’m assuming that the customer is also the passenger (not true in many cases, a company may pay for your flight, so you the company in the customer and you the passenger).

The actual problem the customer is dealing with is that they have thousands of flights, tens or hundreds of thousands of seats and millions of customers competing for those seats.

Let us see if we can breaking it down to a model that can work for this scenario.  Customers deserve its own document, but I wouldn’t store the bookings directly in the customer document. There are many customers that fly a lot, and they are going to have a lot of booking there. At the same time, there are many bookings that are made for a lot of people at the same time (an entire family flying).

That leaves the Customer’s document with data about the customer (name, email, phone, passport #, etc) as well as details such as # of miles traveled, the frequent flyer status, etc.

Now, we have the notion of flights and bookings. A flight is a (from, to, time, plane), which contains the available seats number. Note that we need to explicitly allow for over booking, since that is a common practice for airlines.

There are several places were we have contention here:

  • When ordering, we want to over book up to a certain limit.
  • When seating (usually 24 – 48 hours before the flight) we want to reserve seats.

The good thing about it is that we actually have a relatively small contention on a particular flight. And the way the airline industry works, we don’t actually need a transaction between creating the booking and taking a seat on the flight.

The usual workflows goes something like this:

  • A “reservation” is made for a particular itinerary.
  • That itinerary is held for 24 – 48 hours.
  • That itinerary is sent to the customer for approval.
  • Customer approve and a booking is made, flight reservations are turned into actual booked seats.

The good thing about this is that because a flight can have up to ~600 seats in it, we don’t really have to worry about contention on a single flight. We can just use normal optimistic concurrency and avoid more complex models. That means that we can just retry on concurrency errors and see where that leads us. The breaking of the actual order into reservation and booking also helps, since we don’t have to coordinate between the actual charge and the reservation on the flight.

Overbooking is handled by setting a limit of how much we allow overbooking, and managing the number of booked seats vs. reserved seats. When we look at the customer data, we show the customer document, along with the most recent orders and the stats. When we look at a particular flight, we can get pretty much all of its state from the flight document itself.

And the plane’s stats are usually just handled via a map/reduce index on all the flights for that plane.

Now, in the real world, the situation is a bit more complex. We might give out 10 economy seats and 3 business seats to Expedia for a 2 months period, so they manage that, and we have partnership agreements with other airlines, and… but I think that this is a good foundation to start building this on.

More posts in "Modeling exercise" series:

  1. (28 Oct 2014) The grocery store’s checkout model process approach
  2. (21 Oct 2014) The grocery store’s checkout model
  3. (06 Jun 2014) Flights & Travelers



Interesting case of document database normalization (i mean flattening the document structure by separating nested entities and promoting them to independent documents). IMHO there's still something that could be improved: there's no seat information in the booking document - so in order to know your seat you have to load a flight document and perform a manual search for a seat with matching booking ID, and database is not going to help you with that.

Ayende Rahien

Rafal, The actual seating information is usually not attached to a booking. It is determined on the flight, and is subject to different changes.

Dominic Zukiewicz

What I find really clever about your approach here is you aren't trying to just denormalize what was given from the domain and make it work as a data model.

You are actually diving deeper into the domain much than the presented data model and actually going up to the use-case and asking:

"Well, a customer does have bookings, and yes aflight does have seats ... but when does a customer need to know what seat they have? If they book a flight a year in advance, do they choose their seat?"

And from experience, NO!. You only know about 2 days in advance where you are going to sit, as you check-in online and pick it then.

So "a customer booking a seat" is actually an incorrectly defined use-case from the business perspective. You've just clarified the process of the business and built your model from that; in essence, you book a reservation on a flight, and at some later time, the check-in process allocates you a seat.

Clever analysis!

Ayende Rahien

Dominic, That is why it is usually very hard to actually do sample domain modeling. Because the actual model really depends on the kind of business rules you deal with. I like to always ask what kind of paper forms they are using, because a lot of the time, that really reflects the real business process communication lines. And people come and try to do things in software and impose their own view on the business processes.

Kijana Woodard

"And people come and try to do things in software and impose their own view on the business processes."

And then when the software is deployed, the execs see that it doesn't meet their view, so changes are rushed in at the last minute.

And then the actual users just have to live with it, even though it doesn't match their view at all. :-]


Design small aggregate http://dddcommunity.org/wp-content/uploads/files/pdfarticles/Vernon2011_1.pdf

Kijana Woodard

Oh, the underscore got crunched.


"And people come and try to do things in software and impose their own view on the business processes"

As awkward as it might sound, this is not always a bad thing. Depends. As always. There are number of small companies, who somehow operate successfully on a daily basis and yet, when you look at them closely, there are no defined processes, just individual habits (even among people with same set of obligations) with loose coupling on the points where people need to interact. In these companies a software can be a boot that kicks them into more defined and organized operating mode.

Ayende Rahien

Urmo, The problem is that many times, the software's idea of what needs to be done is very far from the current (informal) processes. That can create one of several options, sometimes is leads to well defined process that works well. Other times, it leads to jumping through hops to get the system working so people can just do their jobs.


I was not referring to the cases, where software is introduced/developed just by throwing it at the customer users face. It mostly on the cases, where software is either developed specifically for the company or heavily customized. In both cases, customer has to start answering question "how do you do X" in more formal way. And that can lead to many good things.

Ayende Rahien

Urmo, That assumes that the customer is a single entity. I'll have a fully blog post about this in a bit.


If customer stakeholders are not acting as a single entity, every kind of development is hard. Looking forward for your take on this.

Ayende Rahien

Urmo, see: http://ayende.com/blog/167009/your-customer-isnt-a-single-entity

Comment preview

Comments have been closed on this topic.


  1. How to waste CPU and kill your disk by scaling 100 million inefficiently - 5 hours from now
  2. RavenDB Conference 2016–Slides - about one day from now

There are posts all the way to Jun 01, 2016


  1. The design of RavenDB 4.0 (14):
    26 May 2016 - The client side
  2. RavenDB 3.5 whirl wind tour (14):
    25 May 2016 - Got anything to declare, ya smuggler?
  3. Tasks for the new comer (2):
    15 Apr 2016 - Quartz.NET with RavenDB
  4. Code through the looking glass (5):
    18 Mar 2016 - And a linear search to rule them
  5. Find the bug (8):
    29 Feb 2016 - When you can't rely on your own identity
View all series


Main feed Feed Stats
Comments feed   Comments Feed Stats