Nobody has started this yet — be first.
Business impact
This is a sign error in the exact statement responsible for one of this project's two core locking strategies. Left alone, every optimistic reservation would either corrupt the SKU's numbers or (thanks to a database safety net) fail outright with a confusing error -- either way, any deployment configured to use LOCK_STRATEGY=optimistic is completely broken for its one job: correctly tracking how much stock is left.
Problem
Reserve against a SKU using the optimistic strategy fails with a low-level, confusing Postgres error ("current transaction is aborted, commands ignored until end of transaction block") instead of succeeding.
Current behavior
OptimisticStrategy.Claim's UPDATE has available = available + $2 instead of available = available - $2, which breaks sku_inventory's CHECK (available + reserved + sold = total) constraint and aborts the whole transaction.
Expected behavior
Claiming stock should succeed normally: available decreases by the claimed quantity, reserved increases by the same amount.
Steps to reproduce
go test ./tickets/tests/... -run TestTicket12 -vWhy this matters
OptimisticStrategy.Claim's has instead of -- claiming stock is supposed to move units out of available, not add more. Because has a constraint, adding to while also adding to breaks that balance ( doesn't move), so Postgres itself rejects the -- the bug doesn't silently corrupt data, it hard-fails every claim attempt. That's a lucky consequence of the schema's own safety net, not something the code did on purpose; a schema without that constraint would have silently let stock counts run away in the wrong direction.
Suggested approach
Compare the sign on the available assignment in OptimisticStrategy.Claim's UPDATE against ConditionalStrategy.Claim's UPDATE in the sibling file pkg/inventory/conditional.go -- both strategies are claiming the same thing and should move available the same direction.
Acceptance criteria
Verification
TEST_DATABASE_URL=postgresql://... go test ./tickets/tests/... -run TestTicket12 -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/optimistic-sign-flipFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin fix/optimistic-sign-flipSubmit 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 inUPDATEavailable = available + $2available = available - $2sku_inventoryCHECK (available + reserved + sold = total)availablereservedtotalUPDATESKIP 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.