Build1 distinct publisher3 min readUpdated
A dev.to walkthrough separates content identity from operation identity: fingerprints catch a changed payload, idempotency keys catch the order created before the response died.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
A dev.to walkthrough of a four-field order form (first name, last name, amount, price, POSTed to /api/orders) draws a line that most codebases collapse into one attribute in JSX [1]. Disabling the submit button while the request is in progress is useful, the post says, but it improves the user experience only and provides no technical guarantee [2].
The list of ways a duplicate still arrives reads better as a taxonomy than as a warning: a double click, a retry after a network error, a resent HTTP request, two handlers running close together, and a refresh or navigation back to the page [3]. A disabled button covers one of those, and only while the component is still mounted and still knows a request is outstanding. The case it cannot touch is the one the post opens with: the request reaches the server, the order is created, the response never reaches the client, the user submits again, and you have Order #101 and Order #102 for one intended purchase [4].
That failure needs operation identity. The post defines idempotency as executing the same logical operation multiple times producing no more side effects than executing it once, and puts the weight on "logical": one logical operation can become several HTTP requests through retries, timeouts, or user interaction [5][6]. The mechanism is a client-generated key, crypto.randomUUID() sent in an Idempotency-Key header, reused on any retry of the same operation [7][8]. When the server sees a key it has already handled, it can treat the request as a possible retry rather than new work [9].
The key alone is not enough, and the counterexample is the useful part of the piece. A client-side bug resends the same key with amount changed from 2 to 10 [10]. Operation identity says retry; the content has changed, and the server needs a way to determine that this is not a valid retry [11]. Hence the fingerprint: a stable representation of the business-relevant content of a request, the same when the effective content is the same, different when any meaningful value changes [12].
Most of the work in a fingerprint happens before any hashing. The post trims the name strings, coerces amount through Number, and converts price to a minor unit with Math.round(price * 100) to avoid floating-point inconsistencies [13]. The normalized object is then JSON.stringify'd into a canonical string, which can act directly as a local fingerprint for in-client comparison, with a SHA-256 digest of that string via crypto.subtle.digest as the compact form for persistence or server-side storage [14][15][16].
Note where each half stops. Content identity cannot deduplicate on its own: two genuinely separate orders with the same name, amount, and price produce the same fingerprint by construction, so a server that rejects repeated content rejects a legitimate second order [17]. Operation identity cannot validate on its own, which is what the changed-amount case demonstrates [11]. The pair is not belt and braces, it is two different questions asked about the same request.
If you are implementing this, the normalization function stops being a helper and becomes a contract. Any divergence between client and server on trimming or on the cents rounding yields different fingerprints for identical business content [18], which converts a retry into a conflict. The second thing to settle is what the server actually returns when the key matches and the fingerprint does not; the material here establishes that the server must be able to tell this is not a valid retry, but does not specify the response [11]. The post also names a third concept alongside fingerprints and idempotency, meaningful dirty state, framing the three as distinct things that prevent many common form-submission bugs when designed together [19].
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
The example is an order form with values firstName, lastName, amount and price, submitted with a POST fetch to /api/orders with a JSON body of the form values.
Disabling the submit button while the request is in progress is useful, but it only improves the user experience and does not provide a technical guarantee.
A duplicate request can still happen because of a double click, a retry after a network error, a resent HTTP request, two handlers running close together, or a refresh or navigation back to the page.
If the request reaches the server and the order is created but the response never reaches the client, the user submits again and two orders result: first submit Order #101, second submit Order #102, even though the user intended to create only one.
Idempotency means executing the same logical operation multiple times does not produce more side effects than executing it once.
One logical operation may produce multiple HTTP requests because of retries, timeouts, or user interaction, and those requests should not create multiple records on the server.
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.
Self-consistent code walkthrough, single self-published source
Every factual claim traces to one dev.to post authored by an individual. The evidence is internally verifiable — types, fetch calls, normalizeOrder/canonicalizeOrder helpers and a SHA-256 hashing function are shown in full and the normalization example is worked through — which is stronger than assertion alone. But there is no second publisher, no standards or vendor reference for the Idempotency-Key convention, no server-side implementation, and no test, benchmark or incident data.
No adoption signal in supplied material
The source is an explanatory tutorial. It reports no release, deployment, production usage, download, benchmark or customer disclosure, and names no organization using the pattern. Nothing in the supplied material permits an adoption estimate.
Modest claims, but reliability framing outruns the client-only implementation
The post is unusually restrained in one respect: it explicitly refuses to treat the disabled submit button as a guarantee. The overstatement is scope, not volume. It is titled and framed around details that 'make form submissions reliable', yet the actual guarantee depends entirely on unshown server behavior — key storage, replay responses, expiry, concurrent same-key requests — and on the client and server agreeing on normalization rules. Content identity is also presented as the discriminator for a bad retry without noting that identical content cannot separate a retry from a genuinely intended duplicate order. Slightly overstated relative to what is demonstrated.
Individual author visibility; no product, vendor or funding stake evident
The material is a personal technical post on a developer community platform under an individual author's handle. It promotes no product, service, pricing tier, license or employer, and makes no competitive comparison, so the observable incentive is reputational reach rather than commercial. Some mild incentive toward a tidy, confident narrative follows from that, which is consistent with the small positive hype gap.
Mechanism claims well grounded, scope and outcome claims unverified
Confidence in what the code does is high because the implementation is shown and the pattern is stated precisely. Confidence in the story as a whole is limited by a single publisher, no corroboration, an entirely absent server side, and no adoption dimension at all — so the reliability outcome the post claims cannot be assessed from the supplied material.
build
Allow-list the closed set, block-list the open one: 193 thin geo pages, one gate1 distinct publisher
build
A GAN beauty filter is a device budget allocation, not a feature toggle1 distinct publisher
build
Your meter now runs on someone else's machine: signed receipts, fsync, and failing open1 distinct publisher
build
Your inference bill is an architecture defect: declare the task before you call the model1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 21, 2026