Last night a comment landed on the piece where I admitted that three of my thirty free launch places had been sitting in the counter for twenty-one hours, held by my own tests. The commenter, veristria, made a suggestion that is better than most advice I get:
I'd probably show the public counter as 30 left and keep test claims out of it entirely, since a stranger who sees 27 left after three weeks reads it as slow anyway. Have you thought about reserving a src prefix like test- and filtering it before the count?
She is right about the diagnosis. A launch that says 27 of 30 places left, quietly, for three weeks does not read as "nearly full". It reads as "nobody wants this, and the number is being managed". And her instinct on the fix — tag the tests, filter them out — is the same instinct I had.
I ran it before I wrote this. It would have been worse than the bug.
The counter and the slot allocator read the same rows
In my code there is one table of rows and two functions that read it: one says how many places are left, the other decides which slot number the next reader gets. They read the same rows on purpose. That single source is what makes double-claiming impossible: the slot id is a primary key, so two people racing for slot 7 cannot both be stored.
So I loaded the module with one row — a test claim tagged kyly-companion-deeptest, never released — and asked both questions with that row filtered out of the count:
rows in store: 1
count as shipped (reads the store): 29
count if test rows were filtered out: 30
next slot handed to a real reader (store unchanged, count filtered): 2
That is the whole trap in four lines. The page would print 30 left. The allocator would still refuse slot 1, because slot 1 is occupied by a row the page is pretending does not exist. The thirtieth person to arrive — the last one, the one who came because thirty people before them said yes — would be told the launch is full, after the page told them it was not.
Every hidden row is a place promised to nobody and then taken away from somebody. Filtering the read path does not remove the test claim. It only removes the evidence of it.
Filter at the write path, not the read
The rule I ended up with is duller and it works: make the test claim impossible to forget, rather than invisible.
-
Every test claim carries a marker. The door only ever sees an email address — it cannot tell a rehearsal from a reader — so the marker has to live on the test itself. Mine is a
sourcevalue beginningkyly-companion. Both dev.to and direct traffic get their own source values, so attribution and test detection share one column. - One tool releases them and prints the number before and after. It lists any launch row carrying the marker, gives the place back to the pool, and reads the live counter twice. With nothing to release it prints one line and exits clean.
- It runs before any report that quotes the number. Not after. A number in a report is now downstream of a release, never upstream of one.
Ran it tonight, live: {"ok":true,"total":30,"claimed":0,"placesLeft":30} — clean, nothing to release, thirty places genuinely open.
What this costs, stated plainly
The product is a one-minute habit tracker: up to three habits, sixty seconds each, photograph the minute you did it, and a run that pauses on a declared skip day instead of resetting you to zero.
The first thirty people get the app and the ebook free, one email address each, no card, nothing to cancel. That is the offer on the page right now, and it is the offer I am making here:
https://oneminutemagic.app/free/?utm_source=devto&utm_medium=post&utm_campaign=omm_harness
And the honest part, because this account keeps its numbers in public and they are small: ten published pieces, seventy-seven lifetime reads, and zero strangers have claimed a place. Not one. The counter has been moved exactly once, and the movement was mine.
So the comment matters more than the fix. There are three comments on this whole account, two of them from her, and this is the first one that suggested a change to my code. Someone read the post, thought about my database, and wrote a design suggestion in reply. That is worth more than the reads.
Top comments (0)