First on the waitlist: should a cancelled seat be confirmed automatically?
A request to refill cancelled seats in order hides several decisions. Separate joining the queue from attendance intent, then connect seat holds, response deadlines, failed messages and rejoining to a planning specification and engineering/QA handoff.
What did joining the queue actually promise?
Imagine a free workshop with all 20 seats confirmed and three members waiting in order: A, B and C. When someone cancels, should A immediately become an attendee? Availability may have changed since A joined. Before deciding what to automate, establish what the waiting-list application meant and whether attendance intent needs another check.
The aim here is to refill cancelled seats while giving earlier applicants the first opportunity. Queue entry, seat offer and confirmation therefore need different states. Position is an order for receiving offers, not admission. Calling a successful waitlist entry a completed booking would contradict that promise before any allocation code runs.
Ask for the original application wording, when cancellations happen, how long people need to respond and when operations needs a final list. This fixture uses existing member identities, one seat per member and one free workshop. Group requests, payment and priority allocation are outside its scope; the people and numbers are fictional.
Fictional free workshop, capacity 20.
| State | What the applicant can rely on | Seat effect |
|---|---|---|
| Waiting | An offer in intake order if a seat opens | No seat yet |
| Offer active | Time to accept or decline | One seat held for recipient |
| Confirmed | Server has confirmed acceptance | One hold becomes one confirmed seat |
Do not copy another product’s release button blindly
Bevy’s public guide describes different behavior by ticket type: its paid-ticket section has the recipient claim an offer, while RSVP-only release registers the attendee. The same word, release, does not define the same user commitment. It is a useful policy contrast, not evidence that Bevy implements the design below.
Immediate automatic confirmation is the shortest initial idea, but it does not recheck intent. Broadcasting to everyone and taking the first click instead changes priority from intake order to reaction speed. For this case, reserve one seat for the queue head and ask that person to accept within the stated period.
That choice has a tradeoff: the seat remains held while the person decides, and a late cancellation may remain empty. This example prefers the promised opportunity over suddenly shortening someone’s response window. Automatic confirmation could suit a different service if the original application clearly agreed to that transition.
These are decisions for the fictional workshop.
| Option | Benefit | Decision here |
|---|---|---|
| Confirm on cancellation | Fast transition | Reject: current intent must be checked |
| Notify everyone; first click wins | Can fill a vacancy quickly | Reject: does not preserve intake order |
| Hold for queue head, then accept | Preserves order and checks intent | Choose; accept waiting time and late vacancies |
A 24-hour promise also applies to the last person
Set the event to 12 October 2026 at 14:00 and registration close to 11 October at 18:00, both Asia/Seoul. Every new offer lasts 24 hours from creation. The last possible offer is therefore 10 October at 18:00. After that, stop new offers and general registration even when seats open; do not quietly give the last waiter ten minutes.
Order entries by server-accepted intake, using a server sequence to break equal timestamps. A member can have only one active waiting, held or confirmed entry for this event. While a queue exists, new applicants join its tail rather than taking a seat through a still-open general-registration screen.
Counting only confirmed people is insufficient. Confirmed seats plus valid holds must stay at or below 20. General registration must not take the seat currently offered to A. Checking capacity, selecting the queue head and creating the hold must succeed together or leave no partial assignment.
All fixture dates and times use Asia/Seoul.
| Item | Decision | Boundary to check |
|---|---|---|
| Event / registration close | 12 Oct 14:00 / 11 Oct 18:00 | Event start is not registration close |
| Offer window | 24 hours from creation | Resending does not extend it |
| Last new offer | 10 Oct 18:00 inclusive | No new offers or general entries afterward |
| Capacity | Confirmed + valid holds ≤ 20 | Queue entry alone consumes no seat |
| Queue order | Server-accepted intake sequence | Concurrent entries still have an order |
| Rejoin | Explicit new application at the tail | Old link cannot restore old priority |
Sending the message does not confirm the seat
Before a new offer, check the free seat, an active waiter and a full 24-hour window together. Persist an offer with one hold for the queue head, then send its email. Slow delivery must not create another offer or a second hold for the same person. The offer is the record to retry notification against.
Acceptance is a separate decision. Check the recipient, event, current offer and valid hold. The server time checked inside the atomic state transition must be strictly before offer expiry and registration close; equality is already too late. A client-side click timestamp must not override that decision.
First recognize a retry for an offer that is already confirmed and return its existing result. Otherwise someone whose success response was lost could retry and receive an expiry error. Acceptance and expiry cleanup also need one atomic decision boundary. Disabling a screen button cannot enforce these rules by itself.
Check capacity and queue head together. Record either outcome; acceptance is a separate check.
Read the flow
- Free seat, waiter and full 24-hour window?
- Yes: Hold one seat for queue head; create offer → Record decision and seat change; validate acceptance separately
- No: No new offer; record missing condition → Record decision and seat change; validate acceptance separately
Expiry and delivery failure are different outcomes
Decline, withdrawal and expiry end the particular entry or offer and release only its associated hold once. Cancelling a confirmed registration releases that confirmed seat once. Receiving a cancellation twice must not create two vacancies. After a release, assess new-offer eligibility against the current time and queue again.
Email failure is not a decline. Flag it for operations and resend the same offer without another hold or a new deadline. Stop resending once it expires. Keep send attempts, delivery failures, opens and acceptance separate so operations can see what failed. A successful send neither confirms A nor makes the held seat available to B.
Do not automatically requeue someone after expiry. If the new-offer window remains open, that person may explicitly reapply at the tail. Their old link continues to show the old closed offer and must never act on the new application. The examples below compare fixed messages; they do not create registrations or send email.
Four fixed examples, without a live event connection.
Open the example
Poster Workshop, 12 Oct 14:00. One seat is held for you. Accept or decline by 10 Oct 18:00 Asia/Seoul. You are not confirmed yet.
The server confirmed acceptance: Poster Workshop, 12 Oct 14:00, one person. View or cancel it in your registration.
This offer no longer holds a seat. Its old link cannot accept. If new offers are still allowed, you may rejoin at the tail.
Keep the same offer and hold. Check a resend within the original deadline. Do not add a hold or automatically extend the deadline.
Ask AI for cases that break the ordering promise
A broad request to build a waitlist can produce an email feature and a rank display before the policy is clear. Supply capacity, intake ordering, the 24-hour offer, registration close and rejoining rules first. Delegate finding contradictions and drafting test inputs within those decisions, rather than silently letting the answer choose a new policy.
If a proposal says to notify the next person after delivery failure, check when the original hold ends. Offering the same seat again while the first offer is live is unacceptable. An operator extending the deadline is also a policy change, not a detail to import into the specification without a decision.
The prompt below is unexecuted. Review any answer by tracking seat counts: 19 confirmed plus one held becomes 20 confirmed and zero held on acceptance. A repeated cancellation must not create another vacancy. Carry corrections into QA and operating instructions as well as the screen specification.
Example prompt: A free workshop has 20 seats, one per member. Offer cancelled seats in intake order, holding one seat for 24 hours until acceptance. With less than 24 hours until registration closes, stop new offers and general registration. Find ordering or capacity failures involving concurrent cancellations, acceptance exactly at expiry, a lost success response, failed email and rejoining after expiry. Give before/after seat counts, messages, engineering conditions and QA expectations. Do not invent outcomes or external policies.
Specify what each person needs to start implementation
The planning document should record why an offer was chosen over automatic confirmation and why late vacancies are acceptable. The screen specification connects waiting, offered, confirmed and closed states to messages and actions. Include event time and the full response deadline with its zone in email; tomorrow alone is ambiguous for a message read late.
Engineering needs the one-time seat transition conditions, not just visible states. Operations needs linked intake order, offer deadline, end reason, seat changes and notification results. Do not give operators a bypass around capacity, priority or expiry. A necessary exception should become a separate documented policy decision.
W3C’s status-message guidance supports making processing feedback recognizable to assistive technology without moving focus. In this design, distinguish accepting, confirmed and unable to verify using text and appropriate status feedback. Validate the visible message and accessibility behavior together rather than relying on a color change.
Name the behavior each document must settle.
| Role | Record | Cross-check |
|---|---|---|
| Planning | Alternatives, ordering and boundary decisions | 24-hour window and late intake closure |
| Design | State messages, actions and status feedback | Desktop, mobile and keyboard results |
| Engineering | Atomic seat/offer transitions and notification retry | Duplicates, expiry and concurrent requests |
| QA | Inputs, expected and observed results | Seat counts agree with entry states |
| Operations | Delivery failure and capacity discrepancy notes | Original offer, deadline, actor and reason |
One successful acceptance is not sufficient QA
Specify starting states and request order, not only button names. Two concurrent cancellations from 20 confirmed attendees free exactly two seats, then offer one to each of the first two waiters. Check that competing jobs cannot both choose the same queue head or return a cancelled seat twice.
Test just before, exactly at and after expiry. Because the authoritative time is checked inside the state transition, also delay requests before that point. These are acceptance cases to execute after implementation. Clicking the fixed article demonstration is not an integration test of a workshop service.
All times are in 2026, Asia/Seoul. Reset to each stated initial state and run cases separately.
| Input or situation | Expected result |
|---|---|
| 9 Oct 18:00; 20 confirmed, 0 held, 0 free, 3 waiting; one cancellation | 19 confirmed, 1 held for queue head, 0 free, 2 still waiting |
| 9 Oct 18:00; 20 confirmed, 0 held, 0 free, 3 waiting; two distinct cancellations plus a duplicate | 18 confirmed, 2 holds for distinct queue heads, 0 free, 1 waiting; only two releases |
| 9 Oct 18:00; 19 confirmed, 0 held, 1 free, 2 waiting; two concurrent allocation jobs | 19 confirmed, 1 held for first waiter, 0 free, 1 waiting; no duplicate offer |
| 9 Oct 18:00; 19 confirmed, 1 held, 0 free, 1 waiting; new general application | Keep 19 confirmed and 1 held; new entry joins tail, 2 waiting |
| 9 Oct 18:00; 20 confirmed, 0 held, 0 free, 1 waiting; same waiter applies again | Keep 20 confirmed, 0 held and 1 waiting; no duplicate active entry |
| 19 confirmed, 1 held, 0 free, no other waiters; separately accept before, at and after 10 Oct 18:00 expiry | Before: 20 confirmed, 0 held/free. At/after: reject; after expiry transition, 19 confirmed, 0 held, 1 free |
| 19 confirmed, 1 held, 0 free, no other waiters; acceptance races expiry cleanup near 10 Oct 18:00 | Atomic check before expiry: 20 confirmed, 0 held. At/after: 19 confirmed, 0 held, 1 free. Never both outcomes |
| Accepted 9 Oct 18:00; 20 confirmed, 0 held/free/waiting; response lost, same accept retried 11 Oct 18:01 | Return existing confirmation; keep 20 confirmed, 0 held. A passed deadline cannot reverse that success |
| 9 Oct 18:00; no other waiters; separately withdraw waiting (20 confirmed/0 held), decline/expire offer (19/1), cancel confirmation (20/0) | Waiting withdrawal changes no seats. Other cases finish at 19 confirmed, 0 held, 1 free; release once |
| 9 Oct 18:00; 19 confirmed, 0 held, 1 free, 1 other waiter; expired member reapplies then accepts old link | Rejoin behind existing waiter. Allocation holds 1 for original head; reapplicant still waits. Old link returns closed state only |
| Offer created 9 Oct 18:00; 19 confirmed, 1 held, 0 free/waiting; failed email and resend attempts before/after expiry | Before 10 Oct 18:00: same offer, counts unchanged. At/after: no resend; expiry leaves 19 confirmed, 0 held, 1 free |
| 19 confirmed, 0 held, 1 free, 1 waiting; separate new-offer tests at 10 Oct 18:00 and 18:00:01 | 18:00: 19 confirmed, 1 held, 0 free. 18:00:01: keep 19 confirmed, 0 held, 1 free; no new offers/general intake |
Change the assumptions before reusing the handoff
The material below assumes existing member identities, a free single event, one seat per member and intake-order priority. Group seats or priority allocation require a new rule about skipping the queue head. A service that must fill seats until the event begins cannot reuse the 24-hour guarantee and cutoff without reconsidering both.
Walk one fixture together before handoff. If engineering does not hold a seat when creating the offer, design cannot tell the applicant that a seat is held. Update the decision sheet, screen wording and QA inputs together so the next person does not have to ask which version to trust.
For first release, duplicate holds, over-capacity confirmation, expired acceptance and old links changing new applications are blocking defects. After release, inspect offer and notification failure records to locate stalled processing. Email opens are not attendance outcomes; confirmations and cancellations need their own records.
Adapt capacity, application unit and deadlines before use.
Free workshop — waitlist seat-offer handoff Fixture: capacity 20; one seat per existing member identity. Event: 12 Oct 2026, 14:00 Asia/Seoul. Registration closes 11 Oct, 18:00 in that zone. Payment, groups, priority access and capacity reductions are out of scope. Purpose: offer cancelled seats in accepted queue order and reconfirm attendance intent. Joining the queue, receiving an offer and confirmed attendance are different states. Do not promise a vacancy date or admission. Order: server-accepted registration order; break equal timestamps by the server intake sequence. A member has only one active waiting, held or confirmed entry for this event. Do not expose other applicants. Capacity: confirmed seats + valid holds must never exceed 20. Held seats are unavailable to general registration. While an active queue exists, newcomers join its tail. Re-evaluate changed conditions before assignment. New offer: only with a free seat, an active waiter and at least 24 hours before registration closes. Atomically hold one seat for the queue head. Expiry is offer creation + 24 hours. Latest new offer here: 10 Oct, 18:00. After that, stop both new offers and general registration, even if a seat is free. Accept: verify recipient, event, current offer and valid hold. The server time checked inside the atomic transition must be strictly before both offer expiry and registration close. Client click time is not authoritative. Convert one hold into one confirmed seat. Duplicates: acceptance retried for that already-confirmed offer returns the existing confirmation. Never create a hold from an expired offer or redirect its action to another active entry. End: decline, withdrawal and expiry end the specific entry/offer and release its associated hold once. A confirmed cancellation releases its confirmed seat once. Expiry processing and acceptance use the same atomic decision boundary. Rejoin: never restore old priority automatically. A person may explicitly apply again during the new-offer window and joins the tail with a new intake order. Old links continue to show the old closed state. Notification: persist the offer first, then send email tied to it. Send request, delivery failure, opening and acceptance are separate records. Flag failures or unknown outcomes for operations; resend only the same offer without another hold or an automatic extension. Never treat successful sending as acceptance; do not resend after expiry. Screen: show event/date, full response deadline with zone, current state and allowed actions together. Active offer: Accept/Decline. Confirmed: View registration/Cancel. Closed: reason and rejoin availability. Unknown acceptance outcome: query current registration; do not claim confirmation. Audit: connect intake order, offer creation/expiry/end reason, seat counts before/after, acceptance decision time, notification results and operator actions. Operators cannot bypass order, capacity or expiry. Policy changes require a separate decision and document update. Handoff: planning owns ordering/boundaries; design owns messages/actions and accessible status feedback; engineering owns atomic seat/offer transitions and notification retries; QA records inputs/expected/observed results for 12 cases; operations records delivery failures and inconsistent capacity. Release gate: block release for duplicate holds, over-capacity confirmation, expired acceptance or old links acting on a new entry. Retest the same sequence. This fictional design has not been integration-tested against a live event service.
Download the engineering and QA handoff
Sources and example conditions
A fictional free-workshop design. Bevy provides a contrast between product policies; W3C supports the status-feedback principle. Capacity, priority, the 24-hour window and cutoff are choices for this example, not live event outcomes. AI prompts are unexecuted examples. English and Chinese localize the same Korean case.