Skip to content
FeaturesPricingAffiliateBlogHelpAboutContact
Get StartedSign In
Back to Blog
industry2026-05-2312 min read

A customer suggestion was added, then rejected, then added again — dish-suggestions PATCH state-machine + OCC race guard missing

Lars (47) runs De Pannenkoekenmolen pancake place in Antwerp Zurenborg with 2 co-managers (Elise weekdays, Tom weekends). Customer Karin's "Earl Grey lavender crepe" suggestion cycled through 5 status flips in 3 days: new → considering (Elise, chef Marieke starts sourcing lavender honey) → added (Tom, unaware of Elise's note) → declined (Lars, "no creamy desserts, summer waste high") → considering (Elise phones Lars, lavender honey already on prep table) → added. Karin TripAdvisor comment: "The system said no, then yes. Either the owner is dishonest or the system is broken." thMenu support busted 2 wrong theories (stale browser tab, server-side PATCH ordering). Third theory cracked it: PATCH endpoint has zero transition validation AND zero OCC race guard. Body zod-parsed → direct UPDATE. **Two distinct bugs**: (1) State machine not enforced — any-to-any transitions allowed, `added → declined` and `declined → considering` bypasses are meaningless. (2) No OCC race guard — concurrent PATCH last-writer-wins, admin_note silently overwritten. **PR #660 batch X F3** two-layer fix: (1) LEGAL_TRANSITIONS map (new → all three, considering → added/declined/new, added → considering only, declined → considering only); SELECT current status + transition validation + 422 invalid_transition. (2) OCC race guard `UPDATE ... WHERE id = ? AND restaurant_id = ? AND status = <prev>`; meta.changes === 0 → 409 status_changed; UI refresh + retry. Pattern: any PATCH endpoint with a status column in a multi-user workflow needs BOTH LEGAL_TRANSITIONS AND OCC race guard — neither alone suffices (LEGAL-only loses admin_note metadata to last-writer-wins; OCC-only allows silent bad-workflow slip-throughs).

th

thMenu Team

thmenu.com

Found this helpful? Share it.