Why a company slug is not its name

devin.ai posts its jobs on Ashby under the slug cognition. Here is why identifier drift breaks job indexes and filing datasets, and how to build a resolver that survives it.

Type devin.ai into a browser and you get a product page for an AI software engineer. Click through to the careers page and the hosted job board loads from a different address. The Ashby board sits under the slug cognition, because the company behind the product is Cognition. The product is Devin. The domain is devin.ai. The applicant tracking system knows it as cognition.

One company. Four strings. None of them equal to each other.

This is not a trivia item. If you are building a job index, a company database, a funding tracker or anything that joins one dataset to another, this single mismatch is the shape of your hardest bug class. It shows up quietly, it never throws an error, and it silently drops real records on the floor.

What a slug actually is

A slug is a URL-safe identifier chosen by whoever set up the account. On Ashby, Greenhouse, Lever and Workable, the board slug is picked once during onboarding and then it is frozen forever, because changing it would break every live application link. The person who picked it was usually an early recruiter or a founder with an afternoon to spare. They picked what made sense that day.

That means a slug encodes the company name at the moment of ATS setup, not the company name today. Every rebrand, acquisition, product pivot and legal restructuring after that moment leaves the slug untouched. The slug is a fossil.

Cognition is a clean example because the mismatch is intentional and public. The legal and corporate entity is Cognition. The product that got famous is Devin. Marketing bought devin.ai. Recruiting had already set up the board under the company name. Nobody did anything wrong. The strings just diverged.

Now multiply that by every company that renamed itself, every startup that shipped a product more famous than its parent, and every acquisition where the acquired brand kept operating under a new corporate parent.

The naive index and how it fails

The tempting design for a job index is a table keyed on company name. You scrape a board, you take the display name, you use it as the key. It works for a few hundred companies. Then it stops working, and the failure mode is worse than a crash.

Three things go wrong.

You get duplicates. Cognition, Cognition AI, Cognition Labs and Devin become four rows for one employer. A user searching for one of them sees a fraction of the open roles and concludes your index is thin.

You get collisions. Short names are not unique. There are many companies called Apex, Nova, Atlas or Vertex. Keying on the display string merges unrelated employers into one bucket, and now your index is not thin, it is wrong.

You get silent misses on the join. This is the expensive one. You have jobs keyed on a board slug. You want to join them to a filing dataset keyed on a legal entity name, or to a funding dataset, or to a ticker. The join runs, returns rows, and reports no errors. It just quietly returns fewer rows than it should, because cognition never matched Cognition AI, Inc. and nothing in the pipeline was designed to notice.

A join that fails loudly is a bug you fix on Tuesday. A join that fails quietly is a number in a report that is wrong for a year.

Official filings have the same problem, with better tooling

Anyone joining company data eventually hits the SEC, and the SEC solved this specific problem decades ago. Every filer gets a Central Index Key, a numeric CIK that never changes. The company name attached to that CIK can change as often as the company likes. The CIK does not.

You can see the mechanism directly in EDGAR full-text and company search at sec.gov/edgar/searchedgar/companysearch. Look up a company that renamed itself and you will find the former names listed against the same CIK. The identifier is the anchor. The name is an attribute that happens to have a current value.

This is why filing data is joinable and job board data is not. The SEC made the identifier primary and the name secondary. Job boards did the opposite. They made a human-chosen string the primary key and never gave anyone a stable numeric ID to hold onto.

The same design shows up in Form D. A startup raising a private round files a Form D with the SEC, and that filing carries the CIK of the issuer plus the legal entity name, which is frequently nothing like the brand you know. The general instructions and the form itself are published at sec.gov/files/formd.pdf. If you have ever wondered why a funding dataset lists an entity you have never heard of, this is why: the legal name filed with the regulator and the name on the website are different strings, and only one of them is in the filing. We cover the field-by-field read of that document in how to read a Form D filing.

Congressional trade disclosures have the same tension in a different direction. A House filing names an asset in free text, typed by a human, and that text has to be resolved to a ticker before it means anything. The filings themselves live at disclosures-clerk.house.gov, and the whole end to end mechanism is covered in how congressional trading disclosures work. The filings arrive on a 45-day clock under the STOCK Act, which we explain in the 45-day rule and why it matters.

The pattern repeats everywhere. Human-entered strings on one side, stable identifiers on the other, and a resolver in between that nobody budgeted for.

Build the resolver as a real component

The fix is not clever string matching. Fuzzy matching on company names is a trap, because it does not distinguish between Cognition and Cognition Therapeutics, two genuinely unrelated organizations. Edit distance has no idea what a company is.

The fix is to stop treating any name as a key.

Mint your own internal company ID. An opaque integer or UUID with no meaning. Every record in every dataset points at it. This is the one string in your system that is allowed to be a join key.

Attach identifiers as evidence, not as keys. Board slug, primary domain, CIK, LEI, ticker, ATS provider. Store each one with its source and the date you observed it. A company row is a bundle of identifiers, not a name.

Anchor on the domain wherever you can. Domains are close to unique and reasonably stable, and they are the one identifier that appears on both the marketing side and the recruiting side of most companies. The Ashby board for cognition links back to a site, and that site resolves the slug to a real organization. Domain is the cheapest bridge between the ATS world and the filing world.

Keep an alias table with provenance. cognition, Cognition AI, Devin and devin.ai all map to the same internal ID, each with a note about where the alias came from and when. When a new alias appears, you add a row. You never rewrite history.

Never resolve silently. Every automatic match should record a confidence score and the rule that produced it. Every ambiguous case goes to a review queue instead of guessing. A resolver that guesses without logging is a resolver you cannot debug six months later.

Instrument the miss rate. Count the records that failed to resolve. That number is the health metric for the whole pipeline. If it drifts up, something upstream changed, and you want to know that from a dashboard rather than from a user complaint.

What this costs if you skip it

Skipping the resolver is cheap on day one and expensive forever after. The cost compounds in a specific way: bad joins produce plausible output. Nothing looks broken. A funding tracker that misses half of a company's raises still shows raises. A job index that splits one employer into four still shows jobs. A signal that misses a filing still fires on the filings it caught.

You do not find out from an exception. You find out when someone who knows the domain looks at your output and says that a company is missing, and then you discover that it was missing for the entire history of the dataset. Backfilling a resolver after the fact means reprocessing everything, and any downstream numbers you already published were wrong.

Build the identity layer before the analytics layer. It is the least interesting part of the system and the part that determines whether anything above it is true.

Free ways to check this yourself

You do not need a paid tool to work with any of this.

EDGAR full-text search at efts.sec.gov/LATEST/search-index?q= and the company browse pages are free and cover every filer, including former names. The SEC also publishes bulk company tickers and CIK mappings as JSON files you can download directly. House financial disclosures are free at the Clerk's site. Senate filings are free at efdsearch.senate.gov. Most ATS platforms expose a public job board endpoint per slug, so you can verify a board slug yourself in a browser by trying the slug and seeing what loads.

For 13F work, the same identifier discipline applies to holdings, where CUSIPs are the anchor and manager names are the attribute. The reporting timing there is covered in 13F deadlines and the 45-day lag.

None of this is investment advice. It is a description of how public data is structured and where joins break.

The lesson from cognition is small and general. A slug is a name that someone typed once, in a hurry, before the company became what it is now. Treat it as a clue, never as a key.

If you want to see identifier resolution applied to real filings rather than described in the abstract, our Startup Capital Raises Form D report tracks new Form D filings and resolves each issuer entity to the company you actually recognize, so the funding rounds you care about do not disappear behind a legal name you have never seen.


Want the signal instead of the raw filings? Get a free report preview. Prefer the tool to the write-up? Browse all data feeds or connect the free MCP server.