I treated publishing as a queue. The queue lied.
On September 11, the publishing ledger said 29 articles while the public profile showed 30 . I had one stale editor buffer, one repaired series assignment, and no trustworthy answer to a simple question: if I ran the queue again, would it publish a duplicate? TL;DR I was wrong to treat my local queue as the source of truth after a networked side effect. A publish attempt needs a receipt, a…
On September 11, the publishing system reported 29 articles, yet the public showed 30. The reporter faced a stale editor buffer, a repaired series assignment, and an unanswered question: would running the queue again result in duplicate publications? In hindsight, treating the local queue as the source of truth proved to be a mistake.
A successful publish attempt requires a receipt, verification state, and a recovery path that does not assume failure means "nothing happened." Time gates and content fingerprints are only useful after reconciling with the public destination. The reporter now optimizes for an interrupted run being less troublesome rather than a clean run being elegant.
The writer realized that producing a useful article on schedule was not the challenging part of a solo publishing system. The real challenge lay in deciding what the machine could do after the browser timed out between "Publish" and "I can prove it was published." This distinction proved to be the difference between a harmless delayed post and re-publishing the same article to the same readers.
The reporter's queue had several independent histories: the editorial rotation choosing topics, the public list maintained by the platform, and the browser session, including unfinished editor state. The mismatch between the queue and public profile came from an article published through a separate recovery path on June 16, which was genuinely public but intentionally absent from the rotation ledger.
The reporter's mistake was assuming these counts represented the same thing. The stale editor buffer made this mistake particularly dangerous, as opening the new-post page could restore old article text. If the reporter treated "content in the editor" as "the next draft," a recovery run could turn old state into a new public URL.
The repaired series assignment introduced yet another trap. One article had published successfully on September 4, but adding it to its series returned an HTTP 500. Two days later, the reporter repaired the series on the existing article. The reporter's system did not resemble a queue; it was a small distributed system named a queue due to its friendlier name, which led the reporter to ignore the failure modes.
The old model assumed every step shared one transaction, but browsers, local files, and publishing platforms do not provide such a transaction. The comparison between the queue model and state-machine model reveals the differences in handling various steps in the publishing process. The old model treated each step as having one transaction, while the state-machine model recognized that browsers, local files, and publishing platforms have different outcomes and require separate handling.
The reporter now uses a minimal model with several states to represent the publish attempt: prepared, submission_started, published_verified, metadata_incomplete, verification_pending, and recovered_existing. The identity of the content, separate from its placement, remains constant throughout the process.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.