Library / SDK
paralleldrive/cuid avatar
paralleldrive/cuid

cuid is deprecated: what the collision-resistant ID spec still does well, and what to use instead

Deprecated collision-resistant id spec. Insecure because it leaks timestamps. Use cuid2 instead.

3,502 stars118 forksJavaScriptNOASSERTION

At a glance

What is it?
The paralleldrive/cuid package is marked deprecated because its IDs leak timestamps. This is a walkthrough of the mechanism, a first install, the fingerprint design, and the migration question to cuid2.
Who is it for?
Use cuid only if you are maintaining an existing system that already stores cuid values in a database or a public URL and you cannot migrate the data. Do not adopt it for new work: the README itself marks it deprecated because the timestamp segment leaks information, and the announced replacement is cuid2.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What problem cuid was built to solve, and who it was for

The README frames cuid around a specific failure mode of distributed applications. When IDs are generated on many hosts, or on clients that are offline, pseudo-random generators seeded with the same millisecond can produce the same value. The README describes the consequence plainly: applications report v4 UUID collisions when ID generation is spread across many machines generating IDs in the same millisecond, and a database without a unique constraint will return the first matching row, so users start seeing data that belongs to someone else. The stated audience is anyone building horizontally scaled web applications who wants to generate IDs on the client or on any write host without a round trip to the database. The README also argues that letting the database assign IDs forces clients to send incomplete records and wait, which rules out fast client-side algorithms. That is the case cuid was designed against.

The five segments inside a cuid, and why the timestamp is the problem

A cuid is a fixed structure, not an opaque random blob. The README breaks one down as `c - h72gsb32 - 0000 - udoc - l363eofy`, and names the groups in order: a leading `c` that identifies the string as a cuid and makes it usable as an HTML entity ID, a timestamp, a counter, a client fingerprint, and a random tail using cryptographically secure libraries where available. The counter exists because a single process might otherwise generate the same random string, and the README notes the probability worsens as processors get faster. The monotonic property is a deliberate feature: cuids from the same process increase monotonically when fewer than 10000 are generated in the same millisecond, and across processes they stay time-ordered if the clocks are synchronized. That makes them binary-searchable as database primary keys, which the README links to a discussion of monotonic functions in MySQL. The same timestamp segment is what the deprecation notice calls out. Because the value encodes when it was created, an ID that appears in a URL or an API response tells an observer something about the record. The README's status line is unambiguous: deprecated due to security, use Cuid2 instead. Its note goes further and says all monotonically increasing, auto-increment and k-sortable IDs share the issue, and that UUID V6 through V8 are insecure for the same reason because they leak information. It links three exploit write-ups, including a password reset compromised through a guessable ID and unauthorized access to private GitLab issues through guessable IDs. Read that as the project's own position on its former design, not as a claim about any particular deployment.

Installing cuid and generating your first ID

The README gives the install command with the save flag, and the package is published under the name cuid. Run it in a project directory and npm writes the dependency into package.json.

bash
$ npm install --save cuid

The README does not document a version pin or a Node version floor, so treat whatever npm resolves as the version you get. The README shows both module styles. The ESM form imports the default export and calls it, and the comment in the example shows the shape of the output: a lowercase alphanumeric string starting with c.

js
import cuid from 'cuid';

console.log( cuid() );

// cjld2cjxh0000qzrmn831i7rn

The Node style uses require and produces the same shape.

js
var cuid = require('cuid');
console.log( cuid() );

// cjld2cyuq0000t3rmniod1foy

Both examples print a 25-character value. Note that the package.json in the repository carries version 3.0.0 while the most recent published releases listed are v2.0.1 and v2.0.0 from 2018, with v2.0.0 described as a broken modular build, so the repository state and the published release history do not line up. Verify the installed version yourself rather than assuming.

How the client fingerprint is derived on Node, in browsers and in React Native

The fingerprint segment is the part of the design that gets the least attention and carries the most environment-specific behaviour. In browsers, the README states the first characters come from the user agent string and the supported mimeTypes, concatenated with a count of variables in the global scope, then trimmed to four characters. The README notes mimeTypes are fairly unique except in IE, which always returns 0, so in that browser the fingerprint loses most of its distinguishing power. In Node, the first two characters come from process.pid and the next two from the hostname. React Native gets its own fingerprint module. The package.json browser field maps lib/fingerprint.js to lib/fingerprint.browser.js and lib/getRandomValue.js to lib/getRandomValue.browser.js, and a separate react-native field maps the same two modules to react-native variants. That means the same call produces structurally different strings depending on where it runs, and the fingerprint is derived from observable environment values. That is a design decision with a privacy dimension the deprecation notice does not spell out, but it follows from the same reasoning that retired the timestamp.

Where cuid is the wrong tool now

The honest limitation is stated by the project itself: the IDs leak timestamps, and the README says to use Cuid2 instead. If an identifier is exposed to users, appears in a URL, or is used anywhere near an authorization check, a timestamp-bearing ID is the wrong choice. The README's own linked exploits are about guessable IDs leading to account takeover and access to private issues, and while those write-ups concern other ID schemes, the reasoning the README applies is the same one it applies to cuid. There is a second, quieter limitation. The fingerprint depends on hostname and process ID in Node, and on user agent and mimeTypes in the browser, so the collision resistance of the whole string is partly a function of how unique your runtime environment happens to be. Cloned virtual machines and identical container images reduce that uniqueness, which is exactly the scenario the README cites as the motivation for the design in the first place. The counter also rolls over, per the README, if the value gets too big, and the monotonic guarantee holds only below 10000 IDs in a single millisecond from one process. Beyond that, the ordering property stops being something you can rely on.

cuid2 and NanoID: what actually differs in approach

The README names Cuid2 as the replacement, and the search phrasing people use around this package includes cuid vs cuid2 and Cuid2 vs NanoID, so the comparison is worth stating precisely. Cuid2 is the successor from the same project, and the difference that matters is the one the deprecation notice gives: cuid2 does not carry the timestamp segment that makes cuid leak creation time. NanoID takes a different route again. It is a small random ID generator, and the reason it comes up in the same conversations is that it is the other widely used answer to the same question of generating IDs without a database round trip. The trade is the one the cuid README lays out in its motivation section: purely random IDs give up the monotonic, binary-searchable ordering that cuid was designed to provide, and the README argues that random IDs lack sufficient entropy across separate processes to guarantee against collisions. If you need sortable primary keys, that argument still applies to whatever you pick. If you do not, the ordering property was never buying you anything. The related searches also show people wiring cuid into Drizzle ORM and Prisma, which is a sign the package lives on in schema definitions long after the deprecation notice went up.

Maintenance status, licensing and what an upgrade costs

The repository is not archived, and the last push was on 2026-09-19, so there is recent commit activity. That activity does not change the deprecation status, which is a statement in the README, not a build artefact. The published release history tells a different story from the repository: the most recent releases listed are v2.0.1 and v2.0.0, both from 2018-01-05, and v2.0.0 is annotated as a broken modular build. The package.json in the repository declares version 3.0.0, so anyone reading the source and anyone reading the npm release page may be looking at different things. The toolchain in devDependencies is dated too: babel-polyfill 6.26.0, babel-preset-env 1.7.0, testcafe 2.2.0, uglify-js 3.17.4. The build script runs browserify and uglifyjs to produce dist/cuid.js and dist/cuid.min.js, and prepare runs the build, so installing from git triggers a build.

bash
npm run build

On licensing, package.json declares MIT, while the repository metadata given here reports NOASSERTION, which means the licence could not be identified automatically. Those two sources disagree, and the LICENSE file at the repository root is the thing to read if the distinction matters to you. This is not legal advice. The upgrade cost is the real question. Migrating away from cuid means reissuing identifiers that may already be stored in databases, cached, indexed in search engines, or printed on documents. There is no rollback path documented in the README for such a migration.

Editorial conclusion

Use cuid only if you are maintaining an existing system that already stores cuid values in a database or a public URL and you cannot migrate the data. Do not adopt it for new work: the README itself marks it deprecated because the timestamp segment leaks information, and the announced replacement is cuid2. Before anything else, check whether your stored IDs are exposed to users or used in authorization checks; if they are, the leak is the whole problem, not a footnote. Then read the cuid2 repository and decide whether a migration is cheaper than reissuing identifiers.

Frequently asked questions

What is a cuid?

A cuid is a collision-resistant identifier produced by the cuid package, structured as a leading c, a timestamp, a counter, a client fingerprint and a random tail. The README describes it as safe for HTML element IDs and unique server-side record lookups, and it is 25 characters long in the examples shown.

What is the difference between a UUID and a cuid?

The cuid README argues that GUID and UUID specifications cannot satisfy all the requirements modern applications have, particularly generating IDs on disconnected clients without collisions, and that V4 UUIDs are insecure because future values of many random algorithms can be predicted. cuid adds a counter and a client fingerprint to reduce collisions across hosts, and its timestamp segment makes IDs from one process monotonically increasing.

Is cuid still safe to use?

The README marks the project as deprecated due to security and says to use Cuid2 instead, on the grounds that the IDs leak timestamps. The notice also states that monotonically increasing and timestamp-based IDs generally share that issue.

How do I install cuid in a Node project?

The README gives the command npm install --save cuid, after which the package can be imported as an ESM default export or required in Node style. Both examples in the README call the function with no arguments and print a 25-character string.

Official sources

  1. Issues
  2. paralleldrive/cuid on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/paralleldrive-cuid.svg)](https://hysenlabs.com/projects/paralleldrive-cuid)