Nobody has started this yet — be first.
Business impact
This project's entire reason for existing, stated plainly in its own README, is "100 units of stock, 50,000 simultaneous clicks, and EXACTLY 100 must succeed." With this bug, the 100th buyer -- the one asking for exactly the last unit of remaining stock -- gets a "sold out" rejection even though there is precisely enough stock to satisfy them. In a real flash sale that is a customer who did everything right and got turned away for no reason, a lost sale, and (if anyone compares "units sold" against "units in the warehouse" afterward) a support ticket asking why inventory does not match what was reported sold.
Problem
POST /v1/skus/{id}/reservations for a quantity exactly equal to the SKU's current available returns 409 Conflict ("insufficient stock"), even though there is exactly enough stock.
Current behavior
Reserving exactly 5 units when 5 are available is rejected with a 409, and ConditionalStrategy.Claim's WHERE clause uses a strict available > $2 instead of available >= $2.
Expected behavior
A request for exactly the remaining available stock should succeed (201 Created), leaving available = 0. Only a request for more than what's available should be rejected.
Steps to reproduce
go test ./tickets/tests/... -run TestTicket01 -vcurl -X POST localhost:8081/v1/skus -d '{"sku_id":"demo","quantity":5}'curl -X POST localhost:8081/v1/skus/demo/reservations -d '{"quantity":5}'Why this matters
ConditionalStrategy.Claim (the default locking strategy) is a single atomic conditional UPDATE ... WHERE available >= $2. The WHERE clause's comparison operator IS the entire correctness boundary this project is built around -- get it wrong by one character and the "exactly N must succeed" guarantee is violated in the conservative direction (under-selling instead of overselling), which is safer than overselling but is still a real, measurable bug against the documented contract.
Suggested approach
Look at the WHERE clause in ConditionalStrategy.Claim and compare it against the comment directly above the struct definition, which already describes the intended behavior ("re-evaluates WHERE available >= qty"). Zero remaining stock after a successful claim is a valid outcome, not insufficient stock.
Acceptance criteria
Verification
TEST_DATABASE_URL=postgresql://... go test ./tickets/tests/... -run TestTicket01 -v
Hints (0/2)
Try it without hints first — the reading is the exercise.
Working on this ticket
Work on a branch named for the ticket — that's what you'll submit.
Branch off your fork
Sign in to create it automatically, or do it yourself:
$git checkout -b fix/conditional-off-by-oneFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin fix/conditional-off-by-oneSubmit it below
Paste your fork URL and the branch name, with a short write-up of the root cause.
Questions
Ask about anything unclear in the ticket — the maintainer and anyone who has solved it can answer. Please don't post full solutions.
Sign in to ask a question or reply.
Sign inSKIP LOCKEDhttp://localhost:8081localhost:5434flash-saleeveryday-widgetcurl localhost:8081/healthzgo run ./cmd/loadtest -url http://localhost:8081 -sku flash-sale -concurrency 10000Work the tickets in tickets/docs/ (ordered easy → hard); each names one dedicated Go test in tickets/tests/:
export TEST_DATABASE_URL=postgresql://inventory:inventory@localhost:5432/inventory_test?sslmode=disable
go test ./tickets/tests/... -run TestTicket24 -v # a single ticket
./tickets/run_tickets.sh # all 25, clean pass/fail summary
Tickets that don't touch Postgres (02, 07, 17, 19) run fine without TEST_DATABASE_URL; the rest t.Skip cleanly, not fail, if it's unset.
Level 1
Fix a bug
Read existing behaviour, correct it.