Select Page

CUID2 For ColdFusion / CFML

Published: January 14, 2023

A couple of years ago, I built a ColdFusion port of the CUID library which we’ve been using successfully at InVision. The CUID library provides collision-resistant IDs that are optimized for horizontal scaling and performance. Just recently, however, Eric Elliott released Cuid2 – an updated version of the library intended to address some philosophical security issues. I wanted to create a ColdFusion port of his new Cuid2 library.

View this code in my CUID2 For ColdFUsion project on GitHub.

The CUID2 token is guaranteed to start with a letter and be of a consistent, configured length. The values within the token consist of the Base36 character set, which is [a-z0-9]. The ColdFusion port of CUID2 is thread safe and can be cached and reused within your ColdFusion application:

	// Cachced reference to the CUID instance.
	cuid2 = new lib.Cuid2();
	writeDump({ token: cuid2.createCuid() });
	writeDump({ token: cuid2.createCuid() });
	writeDump({ token: cuid2.createCuid() });
	writeDump({ token: cuid2.createCuid() });

Running this ColdFusion code gives us the following output:

token: uem955pnse56id49y6bcmjz8
token: ek9lgqi0mfkh9wmxnb6rvzuc
token: lycfyvl0dlspi0us6smqkkr0
token: x0hhypk7l7k4hga8newn4gnw

The Cuid2.cfc ColdFusion component can be instantiated with two optional arguments:

new Cuid2( [ length [, fingerprint ] ] )

  • length – The desired size of the generated tokens. This defaults to 24 but can be anything between 24 and 32 (inclusive).

  • fingerprint – An additional source of entropy associated with the device. This will default to the name of the JVM process as provided by the ManagementFactory Runtime MX Bean.

Under the hood, the randomness is provided by ColdFusion’s built-in function, randRange(), which is being executed with the sha1prng algorithm for pseudo-random number generation. We can perform a high-level test of the randomness by generating 1,000,000 tokens and then seeing how well these values get distributed into a set of buckets:

	cfsetting( requestTimeout = 300 );
	length = 24;
	cuid = new lib.Cuid2( length );
	count = 1000000;
	tokens = [:];
	buckets = [:];
	BigIntegerClass = createObject( "java", "java.math.BigInteger" );
	// Create buckets for our distribution counters. As each CUID is generated, it will be
	// sorted into one of these buckets (used to increment the given counter).
	for ( i = 1 ; i <= 20 ; i++ ) {
		buckets[ i ] = 0;
	bucketCount = BigIntegerClass.init( buckets.count() );
	startedAt = getTickCount();
	for ( i = 1 ; i <= count ; i++ ) {
		token = cuid.createCuid();
		// Make sure the CUID is generated at the configured length.
		if ( token.len() != length ) {
				type = "Cuid2.Test.InvalidTokenLength",
				message = "Cuid token length did not match configuration.",
				detail = "Length: [#length#], Token: [#token#]"
		tokens[ token ] = i;
		// If the CUIDs are all unique, then each token should represent a unique entry
		// within the struct. But, if there is a collision, then a key will be written
		// twice and the size of the struct will no longer match the current iteration.
		if ( tokens.count() != i ) {
				type = "Cuid2.Test.TokenCollision",
				message = "Cuid token collision detected in test.",
				detail = "Iteration: [#numberFormat( i )#]"
		// Each token is in the form of ("letter" + "base36 value"). As such, we can strip
		// off the leading letter and then use the remaining base36 value to generate a
		// BigInteger instance.
		intRepresentation = BigIntegerClass.init( token.right( -1 ), 36 );
		// And, from said BigInteger instance, we can use the modulo operator to sort it
		// into the relevant bucket / counter.
		bucketIndex = ( intRepresentation.remainder( bucketCount ) + 1 );
		buckets[ bucketIndex ]++;
		Tokens generated: #numberFormat( count )# (no collisions)<br />
		Time: #numberFormat( getTickCount() - startedAt )#ms
		<cfloop item="key" collection="#buckets#">
				<div class="bar" style="width: #fix( buckets[ key ] / 100 )#px ;">
					#numberFormat( buckets[ key ] )#
	<style type="text/css">
		.bar {
			background-color: ##ff007f ;
			border-radius: 3px 3px 3px 3px ;
			color: ##ffffff ;
			margin: 2px 0px ;
			padding: 2px 5px ;

Since the CUID2 token is, essentially, a Base36-encoded value, we can decode that value back into a byte array; and then, use that byte array to initialize a BigInteger class. And, once we have a numeric representation of the CUID2 token, we can use the modulo operator to sort it into a given bucket. Assuming we have 20 buckets, you can think of this operation like:

asBigInt( token ) % 20 => bucket

Now, when we run the above ColdFusion code, we get the following output:

As you can see, the 1,000,000 CUID2 tokens are, roughly, evenly distributed across the 20 buckets. And, in those million keys, no collisions were detected.

I would not necessarily consider my CUID2 port as production ready since no one else has looked at it and I haven’t tried running it in production. But, if you are looking for a CUID2 port in ColdFusion, hopefully this will at least point you in the right direction.

Check out the license.