Listing snapshot: the version of the offer the buyer agreed to
In short
A listing snapshot is the immutable copy of the offer terms written onto an order the moment it is created. The rule for what goes in it is one line: copy anything that determined what was owed, reference anything cosmetic. Without it, a seller editing a price, a policy or an inclusion silently rewrites the terms of orders already agreed under the old ones.
Key takeaways
- Copy anything that determined what was owed. Reference anything cosmetic. The ambiguous middle is 3 fields, and each needs a decision written down.
- The snapshot must be written in the same transaction that creates the order, or a seller edit can land in the gap.
- A live reference to a listing is a retroactive edit channel: the seller changes a price and every open order changes with it.
- Snapshot and version history solve different problems — one binds terms to an order, the other explains what a listing looked like last Tuesday.
- Seller identity, policy text and tax treatment are the 3 attributes teams get wrong, and all 3 fail only in disputes, months later.
A listing snapshot is the immutable copy of the offer terms bound to an order at the moment that order is created. The rule for what belongs in it fits in a line: copy anything that determined what was owed, reference anything that was merely how the offer looked. An order holding a foreign key to a live listing does not record an agreement — it records a pointer to whatever the seller happens to be advertising today.
The failure this prevents is quiet and retroactive. A seller raises a price on Thursday, and every unfulfilled order placed on Tuesday now displays the new one. Nobody edited an order; the order was never holding the number in the first place. By the time a buyer disputes it, the platform cannot answer the only question that matters, which is what they agreed to.
Copy, reference, or decide: three buckets
| Attribute | Bucket | Reason |
|---|---|---|
| Unit price and currency | Copy | It is the number in the agreement. Everything else in the money model is derived from it |
| Quantity, interval or seat claimed | Copy | The order must state what was bought, not what the listing currently offers |
| Commission or fee basis | Copy | A platform changing its fee schedule must not change the split on orders already agreed |
| Cancellation and refund terms | Copy | The most disputed field on the record, and the one sellers edit most often |
| Fulfilment promise — window, method, location | Copy | It is a commitment, not a description, and a buyer relied on it |
| Inclusions and extras | Copy | Removing an included item after the fact is the same as a price change, and reads as worse |
| Title, description prose, photographs | Reference | Cosmetic. Keep a pointer, and accept that improved photos apply to old orders too |
| Category, tags, search attributes | Reference | Merchandising metadata. Nothing was owed on the basis of a category |
Two of those 8 rows deserve emphasis. Cancellation terms are copied because they are the field a seller is most likely to tighten after taking bookings, and because they decide money on the way out. Inclusions are copied because removing one is a price change that does not look like a price change — a room without the breakfast it was sold with is a partial refund waiting to be argued about.
One seller edit, replayed against a live order
The cost of a live reference is easiest to see by replaying one afternoon's edits against an order placed that morning. The middle column is not hypothetical damage — it is what the order page renders.
| Edit | Without a snapshot | With a snapshot |
|---|---|---|
| Nightly price raised | The order page shows the new price. Support cannot tell which figure was charged | The order keeps the agreed price; the listing shows the new one |
| Cancellation policy changed to strict | A buyer who booked under flexible terms is refused a refund by the current policy | The refund is evaluated against the terms in the order |
| Breakfast removed from inclusions | The order silently loses an inclusion, and the dispute is unarguable in either direction | The inclusion is on the order, and the discrepancy is visible on arrival |
| Listing relisted under a different seller account | The order points at a listing owned by someone who never sold it | The order names the seller it was agreed with |
| Listing deleted | The order page breaks, or renders empty fields | The order still renders in full from its own data |
The last row is where snapshots and deletion policy meet. A snapshot is what allows a listing to disappear from search without breaking the order history behind it, and the 4 independent visibility switches that make deletion safe are set out in what a deleted listing owes its past orders.
An order that reads its terms from a live listing is not a record of an agreement. It is a pointer to whatever the seller is advertising right now, and it changes without anyone editing an order.
The three attributes that are genuinely ambiguous
Most fields sort themselves. Three do not, and each needs a decision recorded rather than inferred from whatever the first implementation did.
- Seller identity. Copy the legal entity and the display name as they stood at order time, and reference the profile for anything live such as a current rating or contact route. A seller who rebrands should not retroactively become the party on last quarter's orders. Whether that entity is a row or an isolated tenant changes how the reference behaves, which is the decision in is a seller a tenant or a row.
- Policy text. Store a version identifier plus the rendered text as it was shown, not a link to a page that will be edited. A link to current terms is not evidence of what anyone agreed to, and the failure only surfaces in the disputes where it matters most.
- Tax treatment. Copy the computed amounts and the basis on which they were computed — rate applied, jurisdiction, whether the displayed price was inclusive. Do not copy a rate alone and recompute later. Tax rules change and are jurisdiction-specific, so confirm the current treatment with your own advisers rather than encoding an assumption; what the platform owes here is a faithful record of what was charged and why.
The same reasoning extends to any offer made to any party. A dispatch offer sent to a courier is a snapshot of terms at offer time — this job, this pay, this window — and if the batching algorithm re-prices between offer and acceptance, the courier accepted something that no longer exists. That is one reason batched dispatch has to freeze the terms it presents, alongside the matching argument in why waiting two seconds beats nearest-first.
Where the snapshot lives, and what it is not
- Two shapes work. A JSONB column on the order line holding the copied fields is enough for most markets. A listing_versions table with the order referencing a version id is better where listings change daily and you want to diff 2 versions, at the cost of a join and a retention policy.
- It is not an audit log. The snapshot answers what was agreed; an audit log answers who changed what and when. Both are useful and neither substitutes for the other.
- It is not a cache. Nothing invalidates it, nothing refreshes it, and no code path may update it. If any process writes to a snapshot after order creation, it has stopped being one.
- It is not the order's state. The terms are frozen; what happens to the transaction afterwards moves through the machine described in order states versus order flags.
- It is bound to the unit of supply that was claimed, so it only makes sense once that unit is chosen — the decision in what your marketplace actually sells.
This is a day-1 field on the order table and a 6-month project once orders exist, because every historical row has to be reconstructed from data that has already changed. It is one of the small structural decisions we put in the first build rather than a hardening pass, in the way we scope MVP and product builds. The rest of the schema sits under marketplace architecture and the transaction data model, part of our marketplace and two-sided platform work.
Frequently asked questions
Short answers to the follow-ups this page tends to raise.
What is a listing snapshot in a marketplace?
It is the immutable copy of the offer terms written onto an order when the order is created, so the order records what was agreed rather than what the listing says today. It holds the price, the quantity or interval claimed, the fee basis, the cancellation terms, the fulfilment promise and any inclusions. Cosmetic attributes such as photographs and description prose can stay as references to the live listing.
What happens when a seller edits a listing after an order is placed?
With a snapshot, nothing: the order continues to show the terms it was agreed under, and the listing shows the new ones. Without a snapshot the order changes retroactively — a raised price appears on orders placed before the change, a tightened cancellation policy is applied to buyers who booked under the old one, and a removed inclusion vanishes from an order that was sold with it. No one edits an order, and the order changes anyway.
Should we snapshot the entire listing or only some fields?
Copy the fields that determined what was owed and reference the rest. Copying everything is tempting because it needs no judgement, but it bloats every order row with marketing prose and image references, and it freezes text that everyone benefits from seeing updated. The line is whether a buyer relied on the field: price, terms, inclusions and the fulfilment promise are relied on, a photograph is not.
Do we still need listing version history if we store snapshots?
They answer different questions, so it depends on which you need. A snapshot tells you what one order was agreed under; version history tells you what a listing looked like at any point, including moments when nobody bought. Marketplaces with moderation, seller disputes or price-change rules usually want both, and in that case the snapshot can reference a version id rather than duplicating the fields.
- orders
- immutability
- data model
- disputes
The work behind this page
Builds from our portfolio that this page draws on.
Low Latency Food Ordering Platform
Unified events operations platform: vendor management, order tracking, payments, automated settlements.
MarketplaceAI Lease Management
AI-powered commercial real estate lease management for multi-brand operators — automates lease data extraction, obligation tracking, and portfolio intelligence.
Real EstateRead next
- Order states versus order flags: the distinction that keeps a transaction consistentOne question admits a value to the state machine: does it change which transitions are legal from here? Everything that fails that test is a flag on the record.definition
- Inventory hold: the row that exists so the second buyer is refusedA hold is a record, not a screen state. It names one unit of supply, one claimant, one expiry and one reason — and while it lives, nothing else may overlap that unit.definition
- The unit of supply: the thing your marketplace is actually allocatingNot what you list, and not what you invoice: the unit of supply is the smallest thing two buyers can want at once when only one of them can have it.definition
- Availability: a set of intervals, not a grid of day cellsAvailability is not a stored fact. It is the answer to a question, computed from recurring rules, exceptions and what has already been consumed — and a day-cell table is a cache of that answer.definition
- Available in search, gone at checkout: locating the stale layerRe-ask the source of truth at the moment of failure. If it agrees with the index, your two paths apply different rules; if it disagrees, something is holding a stale copy.diagnostic
- Orders that sit in pending forever: tracing the transition that never firedPending is not one problem. It is orders waiting on an event that never arrived, orders waiting on a human nobody notified, and orders in a state with no way out — and one query separates them.diagnostic
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