Small interactions. Serious guarantees.
A like that survives a retry. A click that finds the right record. Two small examples you can run, break, and borrow.
By Prabir Singh · Reviewed 23 October 2026 · Node.js 24.22.1+
The working notes / Interactive
Go on. Try the awkward case.
Local simulation · synthetic data
No requests sent. No real likes changed.
One reader. One choice.
More than one delivery.
Send a like, then replay it. Imagine the first response was lost after the server saved the choice.
Try this: like → replay twice → undo. The naive counter keeps two phantom likes.
count + 1 / −1set liked = true / falseWaiting for your first requestBoth stores start empty. Send a like to begin.
This models the state change in memory. It does not run SQLite, simulate actual network loss or prove concurrency safety. The downloadable example below tests the database constraint.
The useful part of an engineering story is the bit you can take back to your own project. Here are two: how to make a repeated request harmless, and how to make a click return the right record. Neither requires a new framework. Your package manager gets the afternoon off.
Pick a problem, run an example
| If you are building… | Start here | What you will learn |
|---|---|---|
| Reactions, saved items or preferences | Retry-safe likes | Store the desired state, enforce uniqueness, verify persistence |
| A model viewer, nested editor or scene graph | Trustworthy selection | Separate the clicked shape from the record it represents |
Both files are self-contained JavaScript modules with assertions. Use Node.js 24.22.1 or a later compatible release. No dependency install, account, API key or project checkout is needed. Download each file, read it, then run it from the folder where you saved it. The likes example creates and removes its own temporary database. Neither example contacts this website.
node --version
node anonymous-likes.mjs
node element-identity.mjsExpected output, apart from a possible Node.js experimental-feature warning:
PASS: retries, separate readers, article isolation, reopen, undo
PASS: parent identity, misleading mesh, missing record, cycleThese examples are MIT licensed. You can reuse and adapt them; retain the attribution and license notice. They are learning material, supplied without warranty. See the full example license.
Example one: a retry should not become another like
The article likes on this portfolio use a shared SQLite store. The downloadable example isolates the storage idea from the Next.js route, cookies and interface. It is intentionally small enough to understand before lunch.
The rule is simple: one row per article and reader identifier. The database, rather than an optimistic button, enforces that rule:
CREATE TABLE likes (
article TEXT NOT NULL,
reader TEXT NOT NULL,
PRIMARY KEY (article, reader)
) WITHOUT ROWID;A unique pair means a repeated insert cannot create a second vote for that pair. In the example, INSERT OR IGNORE keeps an already-present row; undo deletes that exact pair. The statements use parameters instead of inserting values into SQL strings. SQLite documents the IGNORE conflict behavior; it is broader than a duplicate-only exception, so do not use it to hide unrelated validation problems in a larger schema.
The request should describe the intended state:
{ "liked": true }Avoid a “toggle” operation for requests that might be retried. Imagine the server commits a like, but the response disappears. A second liked: true preserves the reader's choice. A second toggle would undo it. That is what idempotent means here: repeating the same operation leaves the same state.
Keep the response attached to the write
The example begins a write transaction, changes the row, reads the resulting count, then commits. The result describes the database at that transaction, although another reader may change the total immediately afterwards. A displayed count is a snapshot, not a promise to freeze the internet.
SQLite allows one writer at a time. BEGIN IMMEDIATE acquires the write transaction up front; it can fail when another writer holds it. The example sets a bounded busy timeout and rolls back an active transaction on failure. It does not retry forever or tell the reader a failed write succeeded.
The Node.js 24 SQLite documentation describes DatabaseSync: its operations are synchronous. That fits this small single-server feature, but long queries or lock waits can block the application thread. A high-write workload needs measurement and potentially a different storage or worker arrangement.
What the test proves
The assertions repeat a like ten times, add another reader, check another article, close and reopen the file, then undo twice. This proves those storage behaviors for the tested runtime. It does not prove HTTP authorization, crash recovery, backup restoration or multi-process contention. Reopening a database is useful evidence; it is not a disaster-recovery drill wearing a tiny hat.
Try changing the primary key to include an extra random identifier. The repeated-like assertion should fail. You have just seen why a correctness rule belongs in the database as well as the interface.
What production still needs
This site's API adds a published-article check, strict boolean input, origin checks, rate limits and a random server-issued browser cookie. It stores a hash of that token with the article slug. Reads do not create a cookie; an explicit like or undo does. See the privacy explanation.
This is a browser preference, not a verified person. Clearing cookies or switching browsers creates another identity. Do not reuse this scheme for elections, paid entitlements or anything where one-person-one-vote is a requirement.
Keep the database outside an ephemeral app container. This site mounts a persistent directory; an in-memory database or a file inside a replaced container would lose the total at the next deployment. Multiple independent servers need a deliberate shared-storage design, not separate files that happen to have the same name.
You can try the real interface at the end of an article about server-rendered React. The guide's downloads never call that live endpoint.
Example two: a mesh is not a business record
The BIM viewer case study describes a subtle failure: the mesh under the pointer represented geometry, while the engineering element's identity lived on a parent node. Looking up the mesh name returned the wrong kind of identifier.
The downloadable example uses plain objects shaped like a tiny scene graph. It contains no client data, IFC file or production converter code. Its product-wall-demo names are deliberately synthetic; this is a lookup lesson, not an IFC GlobalId decoder.
scene
product-wall-demo ← owns the element identity
geometry-group
door-demo ← clicked mesh; misleading nameThe resolver walks upward until it finds the nearest product ancestor. It then asks an explicit map for that product's record. If that product is unknown, it returns no result. It does not keep climbing until it finds a convenient answer.
if (node.name.startsWith('product-')) {
return records.get(node.name.slice('product-'.length)) ?? null;
}The distinction matters: a missing record is a recoverable error. A confidently displayed different record can cause someone to make the wrong decision. “Nothing selected” is occasionally the most useful answer your interface can give.
What the test proves
The assertions cover a nested hit, a misleading mesh name, a missing product and a cyclic parent chain. A visited-node set prevents a malformed graph from looping forever.
It does not render anything or perform raycasting. In a real viewer, you must also test the bridge from the screen position to the hit object, the converter's identity mapping, and the behavior after transforms or batching. The original case study describes those concerns separately; this example does not claim to reproduce its benchmark or production tests.
Try removing the parent walk and looking up the mesh name directly. The first assertion should fail. A screenshot might still look beautiful. That is precisely why the assertion exists.
Turn the lesson into a review checklist
Before shipping a small interaction, ask four questions:
- What must remain true? Write one sentence: a repeated request preserves the chosen state; a selected object resolves to its own record.
- Where is that rule enforced? A database key, a resolver, a transaction or a permission boundary should carry it. A disabled button alone is rarely enough.
- Which failure would look successful? A duplicate count and a wrong-but-plausible record are more dangerous than an obvious error message.
- What evidence is missing? Record the limit of each test. Unit tests, browser checks, real-device checks and recovery drills answer different questions.
For a broader example, the offline kiosk study applies the same thinking to network loss. Kyloth's development notes apply it to tenant boundaries and checkout reconciliation, while clearly separating work in progress from a launched product.
Sources and maintenance
Reviewed on 23 October 2026 against the portfolio's like-store implementation and its case-study source notes. The runnable examples use synthetic data and were tested separately from the production service.
- Node.js 24 SQLite API: runtime requirements, synchronous operations and database options.
- SQLite transactions: transaction boundaries, write contention and rollback behavior.
- SQLite conflict handling: what
INSERT OR IGNOREactually does.
When upgrading the runtime or adapting the schema, rerun the downloaded files and add tests for your new failure cases. Passing these examples is a starting point, not permission to skip your application's tests.