Skip to main content
All posts
February 28, 2025Β·2 min readΒ·Diogo Hudson

What happens when you close a quote

Five things, atomically, inside one transaction. Here's the whole list so you know exactly what to trust.

What happens when you close a quote

Closing a quote is the transition point from sales to fulfillment. It's also the single most dangerous transition in any distribution system if you get it wrong.

In a homegrown system, 'closing' might mean changing a status cell in a spreadsheet. In an ERP, it might trigger a cascade of undocumented side effects. In Quotery, it's five explicit steps inside a single database transaction, and every one of them leaves a trace in the ledger. Here's the exact sequence.

The five steps, atomic 1. Lock the quote row with select_for_update(). This serializes concurrent closes on the same quote β€” only one caller proceeds, the rest queue. 2. For every line, lock the matching StockItem with select_for_update() ordered by (product_id, location_id). The ordering is critical β€” it guarantees that two concurrent quotes closing against overlapping sets of products acquire locks in the same order, preventing deadlock. 3. Increment reserved on each StockItem and write a RESERVE row on the StockMovement ledger for each line. Each RESERVE row carries the quote ID, the product ID, the location ID, the quantity, and the timestamp. 4. Build a shortages list of any line that couldn't be fully reserved. This is informational β€” the quote still closes. The caller receives a shortages array with product IDs and the gap between requested and available. 5. Transition the quote status to closed and commit the transaction.

Shortages are information, not failure By design, close_quote does not 409 on low stock. You get back a shortages array with exact numbers. Commercial teams can decide what to do β€” reserve anyway, adjust, or negotiate.

This is the deliberate inversion described in the over-reservation post. Most systems treat stock shortage as a blocking error. We treat it as a signal. The commercial person knows their pipeline better than the system does. They know what's arriving next week, which customers are flexible, and which lines can be split across shipments. The tool's job is to give them the numbers β€” not to make the judgment call.

What rolls back All of it. The transaction is atomic. A DB error at step 3 rolls back steps 1 and 2. You never end up with half a reservation.

In practice, the main failure mode is a database connectivity issue or a deadlock (resolved by the lock ordering in step 2). The caller retries and the transaction runs cleanly. There is no 'stuck quote' state, no 'status says closed but stock wasn't reserved,' no cleanup job that fixes broken state overnight. Atomicity means the state machine has exactly two outcomes: the transaction committed and everything is consistent, or it didn't and nothing changed.

How a quote moves from draft to delivery.

All posts
Short pieces on quoting, inventory, AI, and how small distributors ship a lot of stuff without the fuss.