Marketplaces & Two-Sided Platforms// definition

Availability: a set of intervals, not a grid of day cells

In short

Availability is composed, not stored: recurring supply rules, one-off exceptions, and the intervals already consumed by holds and orders. A day-per-row table is a cache of that composition, and the moment cache and rules disagree, the cache is what the buyer sees while the rules are what the seller believes.

Key takeaways

  • Availability is a query over 3 layers, not a column: rules, exceptions, and consumed intervals.
  • A day-cell table cannot express a partial day, a cross-midnight slot or a minimum stay without contradicting itself.
  • Store instants in UTC and each rule's zone as an IANA name, or twice a year the grid is wrong for a week.
  • The grid is a fine read model for month views and search, and never the source of truth for a write.
  • Materialising a year of cells per listing is a scaling decision made silently, and the hardest one to undo.

Availability is the answer to a question, not a fact you store. The question is "can this unit be claimed for this interval", and the answer is composed from 3 layers: the recurring rules a seller sets, the one-off exceptions they add, and the intervals already consumed by live holds and orders. Model those 3 and the answer is always derivable. Model a grid of day cells instead and you have stored one particular answer, computed at one moment, for one time zone.

The grid is not wrong as a read model. It is wrong as the source of truth, and the difference shows up the first time somebody edits a rule and the cells disagree — because the buyer then sees the cells and the seller sees the rules, and both are looking at the system.

The three layers every availability answer is composed from

  • Recurring rules. What the seller offers in the general case: open Tuesday to Saturday, 09:00 to 18:00, in 45-minute slots; or a rental open year-round with a 2-night minimum. A rule carries its own time zone as an IANA name such as Asia/Kolkata, because that is what makes it survive a daylight-saving change.
  • Exceptions. Specific overrides with a start and an end: closed 14 to 21 August, open late this Thursday, this unit unavailable while it is being repaired. Exceptions win over rules, and they need a reason field if operations are ever going to explain a gap.
  • Consumed intervals. What has already been claimed — live orders, and live holds, which own exclusivity between intent and payment. This layer changes by the second, which is the strongest argument against precomputing anything downstream of it.

Availability at any instant is layer 1, minus layer 2, minus layer 3. Every real question a marketplace asks is that expression evaluated over a window: show me a month, is this interval free, which listings are free this weekend.

One listing, both ways

Take one studio room: open weekdays 09:00 to 18:00, minimum booking 2 hours, closed for maintenance on the third Friday, with a confirmed booking on Tuesday 14:00 to 16:00. What each model can answer unaided:

QuestionComposed from intervalsMaterialised day grid
Is Tuesday available?Partly — 09:00 to 14:00 and 16:00 to 18:00One cell, so the answer is a lie in either direction
Can I book 13:00 to 15:00?No, it overlaps the confirmed bookingCannot be answered; the cell has no interior
What changes when the maintenance day moves?One exception row is editedEvery affected cell is rewritten, and any cell missed is now wrong
What happens across a daylight-saving change?Rules are in a named zone, instants in UTC, so 09:00 stays 09:00 locallyCells generated under the old offset are off by an hour for a week
How much storage per listing per year?A handful of rule rows plus exceptions365 rows, or 35,040 if the grid is quarter-hourly — per listing
The same rules, stored as intervals and stored as day cells

What a day grid structurally cannot hold

  • Partial days. Supply sold in hours needs an interior the cell does not have, and the usual patch — a cell plus a list of busy times — is the interval model wearing a grid costume.
  • Cross-midnight intervals. A 22:00 to 02:00 slot belongs to 2 cells and to neither, and every system that has met this has an off-by-one bug in its history.
  • Minimum stay, notice period and turnaround. These are constraints over a span, not properties of a day. A cell can be unavailable because of a turnaround rule but cannot say why, so the seller cannot tell a cleaning gap from a booking — worked through in modelling a rental calendar with turnaround days.
  • Quantity. Where a listing is 12 identical seats rather than one room, availability is a count against an interval and a boolean cell cannot carry it — really a question about what your marketplace actually sells.

Where the grid is still the right answer

Rendering a month view and filtering search results are read problems with a shape a database index likes, so a projection of day-level availability earns its place. Two rules keep it honest: it is rebuilt from the 3 layers rather than edited, and it is never consulted on the write path — a booking is confirmed against the intervals, inside the transaction that enforces exclusivity, which is the argument in where the second booking should be refused. Breaking the second rule is what produces a listing that is bookable in search and gone at checkout.

A day cell is an answer somebody computed earlier. Treating it as the question is how two buyers end up holding the same afternoon.

Two adjacent decisions are deliberately not settled here. Whether supply is offered as fixed slots or open intervals is a product question before it is a schema question, with its own comparison of fixed slots against open intervals. And where the seller is a person accepting work rather than a unit of stock, availability means "is this seller taking jobs", which changes what a lead is — see the four shapes a lead can be handed out in. What availability owes an order once one exists is in what belongs in an order record.

Getting this layer right early is cheap and getting it wrong is not, which is why it surfaces in the first week of most MVP and product builds involving booking. The rest of the schema sits under marketplace architecture and the transaction data model, and what we build on it is in our marketplace work.

Frequently asked questions

Short answers to the follow-ups this page tends to raise.

How should availability be stored for bookable listings?

Store the 3 inputs, not the output: recurring rules with their own IANA time zone, dated exceptions that override those rules, and the intervals consumed by live holds and orders. Availability for any window is then computed from all 3. A day-per-row table can exist alongside this as a read projection for calendars and search, provided it is rebuilt from the inputs and never written to directly.

Is a table of blocked dates ever acceptable?

Yes, for supply with no interior — a whole property sold by the night, no partial days, no cross-midnight slots, one unit. The trouble is that the constraint rarely holds for the life of the business. The moment a second unit, an hourly option or a turnaround rule appears, the blocked-date table has to be migrated while live bookings sit in it.

Do holds belong in the availability calculation?

Yes. A live hold consumes supply exactly as an order does, and excluding it is what allows a second buyer to reach checkout on a slot that is already spoken for. The distinction that matters is lifetime, not effect: a hold disappears by itself when it expires, so it must be filtered by expiry at query time rather than by a background job having already tidied it away.

How far ahead should availability be published?

Publish a bounded horizon and derive it, rather than materialising cells to infinity. A rolling window — commonly 12 or 18 months for accommodation, far shorter for services — is a rule with an end date, and it belongs on the listing rather than in whatever job generates a calendar. Materialise the horizon and moving it becomes a data migration instead of a configuration change.

  • availability
  • calendars
  • data model
  • bookings
// shipped work

The work behind this page

Builds from our portfolio that this page draws on.

Working on something in this space?

Tell us where you are in a sentence or two. We'll tell you honestly whether we're the right team, and what a sensible first slice of the work looks like.

Start the conversation