npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tiny-ulid

v1.0.0

Published

Make and decode ULIDs.

Downloads

736

Readme

Tiny ULID

Make and decode ULIDs as well as set and read ULID times.

Read the docs!

Examples

Make a ULID

import { makeUlid } from "tiny-ulid"

const ulid = makeUlid()

console.log(ulid) // "01K1BB2NM2JQ01NCZRW8B8M894"

Decode a ULID and read its date

import { toUlid, decodeUlid, getUlidBufferTime } from "tiny-ulid"

const ulid = toUlid("01ARZ3NDEKTSV4RRFFQ69G5FAV")
// Decode to a 16-byte ArrayBuffer
const ulidBuffer = decodeUlid(ulid)
const time = getUlidBufferTime(ulidBuffer)
const date = new Date(time)

console.log(date.toLocaleString()) // "31/07/2016, 00:54:10"

Generate a ULID as an ArrayBuffer first then stringify it

import { makeUlidBuffer, makeUlid } from "tiny-ulid"

const ulidBuffer = makeUlidBuffer()

database.user.create({ id: new Uint8Array(ulidBuffer), /* … */ })

console.log(`Created user with id ${makeUlid({ ulidBuffer: ulidBuffer })}`) // "Created user with id 01K1BBWHP7PMEEAPCGPKW62CTM"

Performance

This package is at the time of writing the fastest way to generate ULIDs (in JavaScript) and about 61x faster than the official ulid package.

1.26x faster than @yi/ulid
1.28x faster than @kiosked/ulid
1.74x faster than wa-ulid
4.79x faster than @std/ulid
6.82x faster than ulid-generator
12.11x faster than @ulid/ulid
19.07x faster than @evokegroup/ulid
60.78x faster than ulidx
61.97x faster than ulid
64.16x faster than ulid-workers

Monotonic Generation

This package is at the time writing the fastest way to generate monotonically incrementing ULIDs (in JavaScript) and about 2.7x faster than the official package.

1.10x faster than ulid-generator
1.87x faster than @kiosked/ulid
1.92x faster than @std/ulid
2.05x faster than ulidx
2.08x faster than wa-ulid
2.28x faster than ulid-workers
2.73x faster than ulid

You can test these numbers for yourself by running pnpm vitest bench --run. These types of benchmarks are also never apples to apples. All these packages have different bells and whistles. This benchmark is only relevant to you if you only care about fast ULID string generation and nothing else.

Bundle Size

This package is at the time of writing the third smallest way to generate ULIDs (in JavaScript).

| Package | Treeshaken | Minified | Gzipped | |--------------------------------------------------------------------|---------------|--------------|--------------| | Tiny ULID | 1,221 bytes | 587 bytes | 394 bytes | | ulid | 4,338 bytes | 1,702 bytes | 874 bytes | | ulidx | 6,891 bytes | 2,762 bytes | 1,264 bytes | | wa-ulid | 102,495 bytes | 96,346 bytes | 43,129 bytes | | ulid-workers | 7,017 bytes | 2,535 bytes | 1,165 bytes | | @ulid/ulid | 1,327 bytes | 1,258 bytes | 649 bytes | | @kiosked/ulid | 4,691 bytes | 1,932 bytes | 1,016 bytes | | @evokegroup/ulid | 7,079 bytes | 3,077 bytes | 1,366 bytes | | ulid-generator | 12,512 bytes | 3,792 bytes | 1,488 bytes | | @std/ulid | 2,332 bytes | 411 bytes | 335 bytes | | @yi/ulid | 1,614 bytes | 265 bytes | 231 bytes |

I got these numbers with this Rollup config:

import { nodeResolve } from "@rollup/plugin-node-resolve"
import commonjs from "@rollup/plugin-commonjs"
import terser from "@rollup/plugin-terser"

export default {
	input: `main.js`,
	output: { dir: `dist` },
	plugins: [
		nodeResolve(),
		commonjs(),
		// Uncomment to test minifying
		// terser({ compress: { passes: Infinity }, ecma: 2020 })
	]
}

The "Treeshaken" column represents using just Rollup's built in tree shaking. The "Minified" column represents using Rollup's built in tree shaking plus Terser's minification. The "Gzipped" column represents using the default Gzip level (6) on the output produced from the "Minified" column. Like I say above, these types of benchmarks are never apples to apples due to different packages having different features to each other. These numbers are only relevant to you if you only care about the smallest ULID string generation and nothing else.