Understanding collision probability
The birthday bound estimates duplicate risk when outputs are independent and uniformly distributed. This guide derives the inputs, reproduces two results, and separates mathematical risk from implementation and operational failures.
Review notes,
The sample-space and probability functions are covered by literal-result tests in this repository.
The calculator models format-compatible CUID2 values and RFC 9562 UUID v4 values, evaluates the standard birthday approximation with a numerically stable operation, and states the independence and uniformity assumptions beside every result.
Step 1: count the modeled output space
CUID2 at length L
N = 26 × 36L−1
The first character is one of 26 lowercase letters; each remaining position is one of 36 lowercase letters or digits. This counts strings accepted by the visible format. It is not a claim that every real generator is perfectly uniform.
UUID v4
N = 2122
RFC 9562 fixes the version and variant fields and specifies that the remaining 122 bits are random or pseudorandom. Generator quality still depends on the implementation's random source.
Sources: the CUID2 implementation documentation describes its leading-letter and length rules; RFC 9562 section 5.4 defines UUID v4's random fields.
Step 2: count opportunities for a duplicate
With n generated values, there are n(n−1)/2 distinct pairs that might match. That quadratic growth is why collision risk becomes material near the square root of the output space rather than only after exhausting every value.
For tiny probabilities, directly computing 1 - Math.exp(-x) can subtract two floating-point numbers that are almost equal and collapse to zero. The live calculator uses -Math.expm1(-x), which preserves those small non-zero results.
Worked example A: one million default CUID2s
- 1. Length: L = 24.
- 2. Space: N = 26 × 3623 ≈ 1.6215519455311624 × 1037.
- 3. Volume: n = 1,000,000, creating 499,999,500,000 distinct pairs.
- 4. Estimate: p ≈ 3.0834627369042937 × 10−26.
Worked example B: one billion 16-character CUID2s
- 1. Length: L = 16.
- 2. Space: N = 26 × 3615 ≈ 5.747921912739067 × 1024.
- 3. Volume: n = 1,000,000,000.
- 4. Estimate: p ≈ 8.69879558810403 × 10−8, or about 0.0000087% under the model.
The shorter form is still a large space, but the change is not cosmetic: moving from 24 to 16 characters increases the modeled probability for the same volume by roughly twelve orders of magnitude.
Reproduce in the calculatorWhat “50% threshold” means
Solving the small-probability model for p = 0.5 gives n ≈ √(2N ln 2). It is a scale marker, not a safe operating limit. Default-length CUID2 reaches that marker at about 4.74 × 1018 generated values; UUID v4 reaches it at about 2.71 × 1018.
Plan for your actual acceptable failure probability, total lifetime volume, retry policy, and number of independent writers rather than targeting the 50% point.
The model cannot detect broken generation
- Biased or repeated randomness: cloned seeds or a faulty random source violate uniformity and independence.
- Application duplication: retries, copied fixtures, cache bugs, and restored snapshots can repeat an ID without a mathematical collision.
- Race conditions: checking before insert is not equivalent to a unique database constraint.
- Adversarial behavior: the birthday estimate describes accidental duplicates, not a targeted attack on a credential or authorization boundary.
Why CUID v1 is not in the calculator
CUID v1 combines a timestamp, counter, host/process fingerprint, and random fields. Treating all 25 visible characters as one independent uniform draw would ignore that structure and produce a precise-looking but unsupported number. For its actual layout and migration implications, use the CUID v1 anatomy guide.