Build1 distinct publisher2 min readUpdated
A Cloudflare Workers audit log duplicated conversations for three separate reasons at once, so every partial fix left the symptom intact. The real lesson is about verification, not dedup.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
Three causes that produce the same visible artefact turn a symptom into a boolean OR. Duplicates appear if two workers both write, or if the text diverges enough to defeat content matching, or if the merge key drifts. Clear one term and the expression stays true [14]. That is what breaks the ordinary production diagnosis loop: ship the fix, look at the dashboard, conclude you were wrong. Each of the three fixes here was correct on its own and none of them moved the symptom [3].
The card count was itself evidence. Two writers account for two cards [4]; four is what you get when a chat runs long enough for the snapshot window to slide and yield a second grouping key on each side [15]. Nobody could read that arithmetic while treating "duplicated" as one bug.
The cheapest step, according to the writeup, was reading real duplicated events out of KV side by side, which made the `AI:` versus `Assistant:` mismatch obvious in about thirty seconds and would never have surfaced in code review [11]. Both workers were internally consistent. They just picked different strings for the same speaker, and the parser had only ever been taught one of them [5]. The instinct fix, dedup on transcript text, would have shipped and failed for exactly that reason [10].
Fix 3 is the one worth arguing about. The stable identifier the team landed on is the room ID parsed out of the owner's live-takeover link, on the grounds that it survives both the sliding window and the question of which worker wrote the event [9]. It does. It also promotes a URL built for a human to click into a schema field. Grouping now depends on that query parameter continuing to exist in a link whose job is something else, with a two-hour first-visitor-line heuristic left in place for events logged before the links existed [9].
Then the sizing. Snapshots carry the last 8 messages to keep events small [6], which means any conversation longer than eight messages guarantees the old key drifts [16]. Fragmentation scaled with conversation length, so the chats an owner most wants to read end to end were the ones that split into the most cards. For a product sold as an AI you can audit, that is the log failing hardest exactly where auditing matters [12].
The fixes live in a private production repo, so the published snippets are the whole of the external evidence [17]. The transferable part is not the regex [8]. It is that a symptom surviving a correct fix is not a verdict on the hypothesis.
Ranked by verification strength, evidence, and original report placement.
Neverclosed is a 24/7 AI receptionist for small businesses that answers website chats and phone calls, books appointments and hands off to a human on request; it runs on Cloudflare Workers, using Durable Objects for live chat and KV for the event log.
The symptom: one conversation was showing up in the owner dashboard as two, three, sometimes four separate cards, making the owner-facing view of the day unreadable and the log look untrustworthy.
It was not one bug but three independent root causes stacked, so fixing any single one did not fix the symptom; each fix looked like a failure until all three were found.
Root cause 1: a refactor left both the live-chat Durable Object and the AI engine worker calling their own maybeLogChat(), so every conversation produced two events written from different vantage points milliseconds apart.
Root cause 2: one worker wrote 'Assistant:' and the other wrote 'AI:'; the dashboard transcript parser knew Assistant but not AI, so in one copy the AI replies were glued onto the end of the customer's message, breaking rendering and any content-based deduplication because the two copies had genuinely different text.
Root cause 3: the engine logs a rolling snapshot of only the last 8 messages to keep events small, and dedup keyed anonymous chats on the 'first visitor line', so as the window slid the first line of snapshot 3 differed from snapshot 1 and long chats fragmented into multiple cards by design.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Detailed but unverifiable first-party account
The mechanism is described precisely and internally consistently, with the actual changed code published inline (no-op maybeLogChat, before/after parser regex, roomOf extractor), and the derived consequences follow from the stated 8-message snapshot and dual-writer facts. But the entire record is one self-authored post about a private production repo: no reviewer, no logs, no reproduction, no third-party corroboration, and the four-card decomposition is not established. That caps evidentiary strength around the midpoint.
One private production deployment, self-verified
Adoption is limited to the author's own live product: the three fixes are reported deployed and checked at the data layer on one fresh production conversation. There are no external adopters of the pattern, no usage or volume figures, no customer counts, and the author concedes legacy events remain fragmented. That is real but minimal deployment evidence.
Mostly proportionate, with generalization stretch
The technical claims are narrow, specific and accompanied by an unprompted caveat about unbackfillable legacy events, which pulls the gap toward zero. Slightly positive because the framing elevates a single-app bug into a general verification lesson, the 'thirty seconds of reading real data' and 'nothing ships unverified' assertions are self-graded, and the strongest structural point (stringly-typed speaker labels across two services) is patched at the parser rather than the write path while being presented as fixed.
Founder marketing plus contest incentive
The author is the builder and owner of the product being described, the post doubles as positioning for 'an AI you can audit' and links back to their earlier post, and it is explicitly entered in a sponsored DEV contest, which rewards compelling bug narratives. These incentives are openly disclosed rather than hidden, and the technical content is specific enough to be self-limiting, so the score is elevated but not extreme.
Low: single self-reported source
Confidence is constrained by source structure rather than by internal quality. One publisher, one author, one first-party post, no independent verification and no measurable outcomes beyond a self-run check. The mechanism and fixes are coherent and plausible for the stated stack, so the account is credible on its face, but nothing in the cluster would surface a mistake or an omission if one existed.
Follow any of these and your For You feed starts watching them — no settings page required.
build
A GPU SQL Engine Lost to One CPU Thread Because a Dispatcher Constant Was 128x Too Small1 distinct publisher
build
Sentry's defaults shipped a lifter's shoulder injury while the scrubbing policy passed its tests1 distinct publisher
build
Prisma v7 stops seeding for you, and the pooled URL will not finish the job1 distinct publisher
build
Four indexes, none of them covering: the 78-second page and the one index that fixed it1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 22, 2026