A delivery window is not a shipping estimate
On Al's Flowers, an order is not finished when Shopify records a sale. It has to become a printed ticket with a pickup or delivery designation, an address, and a time the shop can actually meet. Shipping estimates from a carrier are useful for parcels that leave in a box. Local delivery windows are different: they are promises about route capacity, prep cutoffs, and which bench ticket gets made first. Treating them as a note in the order comments is how same-day slots quietly overfill.
Estimates float; windows consume capacity
A shipping estimate is a range the carrier publishes after a label exists — or a guess the theme shows before checkout based on zone and method. It can slip a day without anyone in the shop rearranging the morning. The customer is watching a parcel, not a van that already left.
A delivery window is a slot on a real route. Morning means the driver loads a batch; afternoon means a second run; closed means the shop is done accepting for that day. Each accepted order consumes arranging time and van space. If checkout offers "today afternoon" after the cutoff, or after the day's capacity is already spoken for, the failure is not a late tracking ping. It is a ticket that cannot be kept.
Cutoff is a product rule, not a shop-floor hope
Same-day availability has to disappear when prep no longer fits before the last route leaves. That is not a Slack reminder for whoever is watching the inbox. It is a rule evaluated when the customer picks a slot and again when they pay — because a cart opened at 11:00 can still be sitting at 16:00 with "today" selected.
Shopify's native local delivery settings cover methods and zones; they do not, by themselves, enforce per-slot capacity or selection expiry at payment. Whatever you use for the picker — app, Checkout Function, or custom validation — the invariant is the same: a slot that is no longer fulfillable must refuse to convert. Soft copy that says "please order by noon" is not a gate.
Put the window on the operational record
Al's Flowers ingests Shopify orders into ops records, then renders delivery and pickup tickets to PDF and pushes them through PrintNode. The fields the bench works from are the ones that matter: recipient, address, card message, delivery versus pickup, and when it is due. If the window only lives in a line-item property the ticket renderer ignores, the shop rediscovers the schedule by opening admin on a phone.
Model the chosen date and window as first-class attributes on the operational order — not free text someone typed into notes. Sort and filter tickets by route window. When a customer changes delivery day after payment, update that record and reprint deliberately; do not leave two papers with two times. The commerce platform remains the money and canonical order authority. Ops owns the schedule fields the printer cares about, derived from what checkout actually locked in.
Stale selections are checkout bugs
The failure mode that shows up on peak days is not exotic. Customer selects a morning window while it is still open, walks away, comes back after cutoff or after the slot filled, and pays. Without a re-validation at checkout completion, the order lands with a promise the shop already closed.
Validate on select for UX. Validate again on complete for correctness. Persist the slot id and the policy version you evaluated — so later disputes are about a recorded decision, not a reconstructed guess from timestamps. The same discipline that makes webhook ingest idempotent on order id applies here: the accepted window is a fact of the order, and retries or admin edits should not invent a second one silently.
What we ask before we schedule delivery slots
How many route windows exist on a normal day, and what is the hard cap per window? When does same-day disappear relative to the last departure — and does that cutoff differ by zone or by product prep time? Is pickup capacity separate from delivery capacity? Who is allowed to override a full slot in admin, and does that override still print on the ticket?
Those answers decide whether a scheduling app plus Checkout validation is enough, or whether you need custom rules tied to your ops pipeline. They also decide what Al's-style ticket generation must read as required fields. Until the window is a gate at payment and a column on the bench ticket, it is still just a shipping estimate wearing florist clothing.
Questions
- Why not treat the delivery window like a carrier ETA?
- Carrier ETAs describe a parcel in transit. A local delivery window consumes arranging time and route capacity the same day. If checkout accepts a slot the shop cannot meet, the failure shows up as an unkeepable ticket — not a late tracking update.
- Where should cutoff enforcement live?
- In checkout validation at payment time, not only in copy or a picker that ran hours earlier. Re-check that the selected slot is still open and under capacity before the order converts, then persist that slot on the operational record the ticket printer reads.
- How does this fit with keeping Shopify as order authority?
- Shopify still owns money and the canonical order id. Custom or app code owns slot rules, capacity, and the ops fields that become PDF tickets. The window the customer paid for must be a structured field downstream — not a comment someone has to retype.