Engineering decisions
Fairness, cost and invites
Edit distance over embeddings
A semantic fallback accepted unrelated short proper nouns on fandom boards, and most of the content is fandom boards.
Replace it with a bounded edit-distance layer guarded by length, an edit budget, a first-letter anchor and tie rejection.
A false accept is the worst failure a recall game can have. Edit distance has no similarity cliff and needs no model in memory.
Meaning-based near-synonyms that aren’t typos now depend on generated synonym sets.
Self-hosted Postgres over a managed BaaS
A game makes many small requests and serves heavy image traffic, which is exactly the usage that metered platforms bill for.
Run Postgres, Fastify and nginx in Docker Compose on one VPS, with Cloudflare caching images at the edge.
The marginal cost per player stays close to zero, and Compose keeps the whole stack movable.
I own backups, tuning and uptime, so automated dumps to object storage were part of the build from the start.
Room codes over a deep-link vendor
Firebase Dynamic Links shut down in 2025, and an invited friend who installs the app often lands on a blank screen.
Use native Universal and App Links on our own domain, plus six-character room codes.
The links cover everyone who already has the app, and codes cover everyone else with no vendor on the growth path.
There is no deferred deep link. A new player types a short code once.
Decaying claims
In a six-player room the fastest thumbs would take every obvious answer, and the person who knows more would still lose.
Each later finder of an answer earns a decaying share of its value.
The race stays, but the best strategy shifts from typing fast to digging deep. The game rewards the skill it is about.
There is more state per answer, because claim order has to be recorded, broadcast and restored on reconnect.
Ghost opponents
A 1v1 queue with no one online is an empty queue.
Replay real recorded runs as opponents, time-compressed to the match length and scheduled through the same claim path as humans.
They play like people because they are people. The curated pool also lets new players get winnable early matches.
The ghost pool needs curation, and the framing has to stay honest: you are playing the community’s answers.