Cuid2
The most secure, collision-resistant ids optimized for horizontal scaling and performance.
Install / Use
/learn @paralleldrive/Cuid2README
Cuid2
Secure, collision-resistant ids optimized for horizontal scaling and performance. Next generation UUIDs.
Need unique ids in your app? Forget UUIDs and GUIDs which often collide in large apps. Use Cuid2, instead.
Cuid2 is:
- Secure: It's not feasible to guess the next id, existing valid ids, or learn anything about the referenced data from the id. Cuid2 uses multiple, independent entropy sources and hashes them with a security-audited, NIST-standard cryptographically secure hashing algorithm (Sha3).
- Collision resistant: It's extremely unlikely to generate the same id twice (by default, you'd need to generate roughly 4,000,000,000,000,000,000 ids (
sqrt(36^(24-1) * 26) = 4.0268498e+18) to reach 50% chance of collision.) - Horizontally scalable: Generate ids on multiple machines without coordination.
- Offline-compatible: Generate ids without a network connection.
- URL and name-friendly: No special characters.
- Fast and convenient: No async operations. Won't introduce user-noticeable delays. Less than 5k, gzipped.
- But not too fast: If you can hash too quickly you can launch parallel attacks to find duplicates or break entropy-hiding. For unique ids, the fastest runner loses the security race.
Cuid2 is not good for:
- Sequential ids (see the note on k-sortable ids, below)
- High performance tight loops, such as render loops (if you don't need cross-host unique ids or security, consider a simple counter for this use-case, or try Ulid or NanoId).
Getting Started
npm install --save @paralleldrive/cuid2
Or
yarn add @paralleldrive/cuid2
CLI Usage
First, install the shell alias for easier access:
# Install shell alias (recommended)
npx @paralleldrive/cuid2 --install
# ✓ Alias added to .zshrc
# Run: source ~/.zshrc
# View all CLI options
npx @paralleldrive/cuid2 --help
Now generate IDs from the command line:
# Generate a single ID
cuid
# tz4a98xxat96iws9zmbrgj3a
# Generate multiple IDs
cuid 5
# pfh0haxfpzowht3oi213cqos
# nc6bzmkmd014706rfda898to
# ...
# Generate a short slug (5 characters)
cuid --slug
# ra3f3
# Generate multiple slugs
cuid --slug 3
# cgejt
# howzq
# sd67n
# Custom length
cuid --length 10
# c94jt94rt4
# Custom fingerprint
cuid --fingerprint "my-server" 2
# mv8nuzaehk1l9pww1wlmzqax
# n04n62wsow10n3l4huidgkle
# Combine options
cuid --length 8 --fingerprint "test"
# ysk16xlf
# Without alias, use the full command
npx @paralleldrive/cuid2
CLI Options
cuid2 [count] [options]
Arguments:
count Number of IDs to generate (default: 1)
Options:
--slug Generate a short 5-character ID
--length <n> Custom ID length (default: 24)
--fingerprint <s> Custom fingerprint for ID generation
--install Install shell alias 'cuid' → 'npx @paralleldrive/cuid2'
--help, -h Show help message
Programmatic Usage
import { createId } from "@paralleldrive/cuid2";
const ids = [
createId(), // 'tz4a98xxat96iws9zmbrgj3a'
createId(), // 'pfh0haxfpzowht3oi213cqos'
createId(), // 'nc6bzmkmd014706rfda898to'
];
Using Jest? Jump to Using with Jest.
Configuration
import { init } from "@paralleldrive/cuid2";
// The init function returns a custom createId function with the specified
// configuration. All configuration properties are optional.
const createId = init({
// A custom random function with the same API as Math.random.
// You can use this to pass a cryptographically secure random function.
random: Math.random,
// the length of the id
length: 10,
// A custom fingerprint for the host environment. This is used to help
// prevent collisions when generating ids in a distributed system.
fingerprint: "a-custom-host-fingerprint",
});
console.log(
createId(), // wjfazn7qnd
createId(), // cerhuy9499
createId() // itp2u4ozr4
);
Validation
import { createId, isCuid } from "@paralleldrive/cuid2";
console.log(
isCuid(createId()), // true
isCuid("not a cuid") // false
);
Trusted by Millions of Apps
Cuid2 is trusted by millions of apps and attracts over 10 million weekly downloads.
Why Cuid2?
Ids should be secure by default for the same reason that browser sessions should be secure by default. There are too many things that can go wrong when they're not, and insecure ids can cause problems in unexpected ways, including unauthorized user account access, unauthorized access to user data, and accidental leaks of user's personal data which can lead to catastrophic effects, even in innocent-sounding applications like fitness run trackers (see the 2018 Strava Pentagon breach and PleaseRobMe).
Not all security measures should be considered equal. For example, it's not a good idea to trust your browser's "Cryptographically Secure" Pseudo Random Number Generator (CSPRNG) (used in tools like uuid and nanoid). For example, there may be bugs in browser CSPRNGs. For many years, Chromium's Math.random() wasn't very random at all. Cuid was created to solve the issue of untrustworthy entropy in id generators that led to frequent id collisions and related problems in production applications. Instead of trusting a single source of entropy, Cuid2 combines several sources of entropy to provide stronger security and collision-resistance guarantees than are available in other solutions.
Modern web applications have different requirements than applications written in the early days of GUID (globally unique identifiers) and UUIDs (universally unique identifiers). In particular, Cuid2 aims to provide stronger uniqueness guarantees than any existing GUID or UUID implementation and protect against leaking any information about the data being referenced, or the system that generated the id.
Cuid2 is the next generation of Cuid, which has been used in thousands of applications for over a decade with no confirmed collision reports. The changes in Cuid2 are significant and could potentially disrupt the many projects that rely on Cuid, so we decided to create a replacement library and id standard, instead. Cuid is now deprecated in favor of Cuid2.
Entropy is a measure of the total information in a system. In the context of unique ids, a higher entropy will lead to fewer collisions, and can also make it more difficult for an attacker to guess a valid id.
Cuid2 is made up of the following entropy sources:
- An initial letter to make the id a usable identifier in JavaScript and HTML/CSS
- The current system time
- Pseudorandom values
- A session counter
- A host fingerprint
The string is Base36 encoded, which means it contains only lowercase letters and the numbers: 0 - 9, with no special symbols.
Horizontal scalability
Today's applications don't run on any single machine.
Applications might need to support online / offline capability, which means we need a way for clients on different hosts to generate ids that won't collide with ids generated by other hosts -- even if they're not connected to the network.
Most pseudo-random algorithms use time in ms as a random seed. Random IDs lack sufficient entropy when running in separate processes (such as cloned virtual machines or client browsers) to guarantee against collisions. Application developers report v4 UUID collisions causing problems in their applications when the ID generation is distributed between lots of machines such that lots of IDs are generated in the same millisecond.
Each new client exponentially increases the chance of collision in the same way that each new character in a random string exponentially reduces the chance of collision. Successful apps scale at hundreds or thousands of new clients per day, so fighting the lack of entropy by adding random characters is a recipe for ridiculously long identifiers.
Because of the nature of this problem, it's possible to build an app from the ground up and scale it to a million users before this problem is detected. By the time you notice the problem (when your peak hour use requires dozens of ids to be created per ms), if your db doesn't have unique constraints on the id because you thought your guids were safe, you're in a world of hurt. Your users start to see data that doesn't belong to them because the db just returns the first ID match it finds.
Alternatively, you've played it safe and you only let your database create ids. Writes only happen on a master database, and load is spread out over read replicas. But with this kind of strain, you have to start scaling your database writes horizontally, too, and suddenly your application starts to crawl (if the db is smart enough to guarantee unique ids between write hosts), or you start getting id collisions between different db hosts, so your write hosts don't agree about which ids represent which data.
