How it was built: a $0 conflict checker over 4.6M live marks
This is the engineering story behind the tool: how a free brand-name conflict checker screens a typed name against roughly 4.6 million live U.S. word marks in a second or so, on infrastructure that costs essentially nothing to run.
The interesting part is not any single algorithm. It is the discipline. Trademark similarity is a domain where a plausible-looking number is easy to produce and hard to trust, so the through-line of the build was measure first, and publish what didn't work. Several ideas that sounded good — a semantic model, a crowded-field signal, calibrating against tribunal outcomes — were built, measured, and found wanting. We kept the measurements and shipped them. The honest account of what we tried and killed is the point of this post.
For the exact weights, cutoffs, and formulas, this post links to the methodology page rather than repeating them, so the two can never drift out of sync.
The problem
The goal was narrow and honest: take a proposed brand name and tell someone, instantly and for free, how much it looks or sounds like marks that already exist on the U.S. federal register — as a preliminary signal, never as a legal opinion.
The naive version is a text search: match the typed name against a column of registered names. It falls apart immediately at scale. In a register of ~4.6 million marks, almost every string has a coincidental near-neighbor, so a raw similarity search rates nearly everything "high." A useful tool has to answer a harder question: is this name closer to an existing mark than chance would predict for a name of its length? That single reframing — similarity above the base rate, not similarity in the absolute — is what shaped the whole engine.
The data pipeline
The register ships as USPTO bulk XML — large daily and annual data files, not an API you can query. The pipeline (etl/) parses those files and loads the live word marks into Postgres, refreshed daily so the copy stays current; the data date is stamped on every result. That gives one queryable table of roughly 4.6 million live marks with the fields the engine needs: the normalized name, its phonetic encodings, a meaning vector, and the goods classes.
The deliberate boundary here is coverage. It indexes live word marks only — not logos or design marks, not trade dress, not common-law (unregistered) rights, and not state or foreign registrations. Naming that boundary up front is part of being honest about what a name check can and can't see. The full coverage limits are on the methodology page.
Four signals, one score
A word mark can collide with an existing one in more than one way, so the engine reads four independent signals rather than one string-distance number:
Sound (phonetic) — two different phonetic encoders (a consonant-skeleton one and a vowel-preserving one) must agree before a pair counts as sounding alike, which kills false matches that share a skeleton but not their vowels.
Spelling (orthographic) — a blend of Jaro similarity and normalized edit distance, chosen so it stays sensitive to letter transpositions without inheriting a coincidental-overlap floor.
Meaning (semantic) — a sentence-transformer embedding, compared by approximate-nearest-neighbor search over the whole corpus, to catch marks that convey a related idea without sounding or looking alike.
Goods-class relatedness — not a fourth weighted term but a multiplicative gate: a strong name match in an unrelated class is dampened, a match in a related class keeps its weight. The gate values are mined from data — how often pairs of goods classes co-occur across real adversarial USPTO proceedings — not hand-assigned.
How these are weighted, how they combine, and where the band cutoffs sit are all documented, versioned, and shown as code on the methodology page. This post won't restate those numbers — keeping them in exactly one place is how the spec and the engine stay honest with each other.
The architecture, end to end
Put together, the path from a raw government data dump to a single 0–100 score is short and legible:
The pipeline end to end: USPTO bulk records refresh daily into Postgres, then each check runs the four signals whose combination is the 0–100 score. The exact weights and cutoffs live on the methodology page.
The front end is a Next.js app; the scoring service is a small FastAPI process sitting next to Postgres. Nothing in that diagram is exotic — the work was in getting each box right and measuring whether it earned its place.
Measure first: the experiments we shipped as negatives
Most of the engineering judgment went into deciding what not to keep. Four ideas were built, measured, and either dialed back or shelved — and rather than quietly dropping them, we published the measurements on the benchmarks page. Publishing negative results is uncommon and hard to fake, which is exactly why it is the most honest signal for a technical reader.
The semantic signal barely earns its keep. The meaning model was supposed to catch conflicts the string signals miss. Measured on labeled pairs, it scored close to chance and was slightly worse on a retrieval A/B — while costing roughly a third of the working set. It stayed in at a modest weight, honestly described as the first thing to cut if compute ever matters, rather than being oversold.
Tribunal outcomes can't calibrate the cutoffs. A tempting idea: anchor the risk bands to who actually wins oppositions. Measured across hundreds of thousands of proceedings, opposition win/loss showed no separation from name similarity (AUC ≈ 0.47) — the outcome is dominated by procedure, priority, and settlements, not resemblance. So the cutoffs are corpus-relative and honest about it, never dressed up as outcome predictions.
The short-name typo "gap" was a metric artifact. A metric suggested short names missed typos, which pointed at a heavyweight spelling-correction index. On the metric that actually matters to a user, recall was already ~0.995; the fancy index moved it by −0.003 for about 500 MB of memory. We fixed the metric and shipped nothing.
Crowded-field density can't lower risk. The intuition was that a name surrounded by many coexisting look-alikes should score lower. Measured, crowdedness correlated positively with confusability, so damping the score that way would have cost accuracy. Shown as context on results, never folded into the number.
The exact numbers, harnesses, and one clean positive result are on the benchmarks page. The pattern across all four: an idea that sounded right, a measurement that disagreed, and a decision that followed the measurement.
Running it for $0
The whole thing runs on essentially free infrastructure: the front end on a hobby-tier host, and the scoring service plus Postgres on a single small cloud VM reachable only through a Cloudflare Tunnel — there is no public inbound port to the box at all.
The one infrastructure lesson worth passing on is a measure-first lesson too. Early on, searches were slow, and the reflex was to blame CPU or memory and reach for a bigger instance. Profiling said otherwise: the bottleneck was disk I/O on a spinning-disk volume, and the working index was being read from slow storage. Moving the database onto an SSD volume fixed the latency outright — a much cheaper change than scaling up, and one we'd have missed by trusting the reflex instead of the measurement. The recurring theme of the build, in infrastructure form.
What this is, and what it isn't
This post describes engineering, not law. The tool it describes is preliminary automated screening on public USPTO data: it reports how similar a name is to existing marks and shows the evidence, and it never states a legal conclusion. A high score means signals worth investigating; a low score means fewer close matches in this dataset, not a clearance opinion.
It is not legal advice and not a substitute for a full clearance search or attorney review, and it is not affiliated with or endorsed by the USPTO. If you want to see the method in full, read the methodology; if you want to see what we measured, including the negatives, read the benchmarks.
Frequently asked questions
Why publish the experiments that didn't work?
Because in a domain where a plausible number is easy to produce, the fact that a tool measured its own ideas and reported the ones that failed is the strongest evidence that the numbers it does show are trustworthy. The negative results — the semantic signal, the tribunal-outcome calibration, the short-name typo gap, and crowded-field density — are on the benchmarks page in full.
How current is the data?
The register is refreshed daily from USPTO bulk data, and the data date is shown on every result, so you always know how fresh the snapshot behind a score is. It is a periodic copy of public records, not a real-time feed and not an examiner's judgment.
Is this legal advice?
No. It is an automated similarity signal built on public USPTO data — not legal advice, and not a substitute for a full clearance search or an attorney. See the methodology for exactly what it measures and the likelihood-of-confusion factors for what a name check structurally cannot assess.