XConvert
Downloads
Pricing

Generate ULID Online

Create ULID identifiers instantly with a simple online ULID generator—ideal for sortable unique IDs in apps, databases, and logs.

Options

ULID = 10 chars timestamp (48-bit) + 16 chars randomness (80-bit). Lexicographically sortable. Crockford base32 (no I, L, O, U).

Generated ULIDs0 ULIDs

ULID Generator - Generate Lexicographically Sortable IDs Online Free

ULIDs (Universally Unique Lexicographically Sortable Identifiers) solve a problem that plain UUID v4 cannot: they are unique like a UUID, but they also sort by creation time. That makes them ideal for database primary keys, event-stream keys, and any system where you want chronological ordering without giving up the coordination-free generation of UUIDs. XConvert's free ULID Generator creates spec-compliant 26-character ULIDs entirely in your browser — no server roundtrip, no logging, no sign-up.

How to Generate ULIDs with XConvert (4 Steps)

  1. Choose your quantity — Enter how many ULIDs you need: a single ULID for a quick test, or bulk generation for database seeding, migration scripts, load-test fixtures, or event-replay payloads.
  2. Pick generation mode — Use the default mode for independent ULIDs (each one gets a fresh 80-bit random tail), or enable monotonic mode so multiple ULIDs generated within the same millisecond keep strict ascending order by incrementing the random component instead of regenerating it.
  3. Click "Generate" — Your ULIDs are produced instantly using the Web Crypto API. The 48-bit timestamp prefix is the current Unix time in milliseconds, and the 80-bit random tail is cryptographically secure.
  4. Copy or download — Copy a single ULID with one click, or export the entire batch as a .txt file with one ULID per line for pasting into SQL INSERT statements, seed scripts, or test fixtures.

What is a ULID?

A ULID is a 128-bit identifier specified by ulid/spec on GitHub, the canonical reference maintained by Alizain Feerasta. Its layout is intentionally minimal: 48 bits of millisecond-precision Unix timestamp followed by 80 bits of randomness, encoded as a 26-character string using Crockford's Base32 alphabet. The alphabet 0123456789ABCDEFGHJKMNPQRSTVWXYZ deliberately excludes I, L, O, and U to avoid visual ambiguity and accidental profanity.

Because the timestamp lives in the high-order bits, ULIDs sort the same way as their creation order under any byte-wise or string comparison. That property is what makes them useful in B-tree-indexed databases: inserts cluster at the end of the index instead of scattering randomly across the page tree like UUID v4 inserts do, which reduces fragmentation and improves cache locality for time-range queries. The 80 bits of randomness give roughly 1.2 × 10^24 possible values per millisecond, so collisions within a single millisecond on a single node are statistically negligible.

ULIDs are fully compatible with UUID storage. Both are 128 bits, so a ULID drops directly into a PostgreSQL uuid column, a MySQL BINARY(16) column, or any other 16-byte field — you only need to convert between the 26-character Crockford Base32 representation and the 16-byte binary at the application layer. The maximum representable timestamp is 2^48 - 1 milliseconds, which is valid through the year 10889 AD.

ULID vs UUID v7 vs KSUID vs Snowflake — Format Comparison

Property ULID UUID v7 KSUID Snowflake
Total bits 128 128 160 64
String length 26 chars 36 chars 27 chars up to 19 digits
Encoding Crockford Base32 Hex with hyphens Base62 Decimal
Timestamp bits 48 (ms) 48 (ms) 32 (sec) 41 (ms)
Random/sequence bits 80 ~74 (after version/variant) 128 22 (10 worker + 12 seq)
Lexicographically sortable Yes Yes Yes Yes (numeric)
Fits UUID column (128-bit) Yes Yes No (needs CHAR(27)/BINARY(20)) No (fits BIGINT)
Standardized by github.com/ulid/spec RFC 9562 (2024) segmentio/ksuid Twitter (2010)
Coordination-free Yes Yes Yes No (needs worker ID)
Specified monotonic mode Yes (counter+carry) Optional (RFC 9562) No Yes (per-worker seq)

Crockford Base32 Alphabet Quick Guide

Index Char Index Char Index Char Index Char
0 0 8 8 16 G 24 R
1 1 9 9 17 H 25 S
2 2 10 A 18 J 26 T
3 3 11 B 19 K 27 V
4 4 12 C 20 M 28 W
5 5 13 D 21 N 29 X
6 6 14 E 22 P 30 Y
7 7 15 F 23 Q 31 Z

The four excluded letters — I, L, O, U — are skipped because they look like digits or each other in many fonts. Decoders typically also treat lowercase as equivalent to uppercase and accept I/i → 1, L/l → 1, O/o → 0 for forgiving input parsing.

Common Use Cases

  1. Time-ordered database primary keys — Use ULIDs as primary keys in tables with high write volume to avoid the B-tree index fragmentation that random UUID v4 keys cause. Because new inserts cluster at the end of the index, page splits drop and cache hit rates rise. Works directly with the PostgreSQL uuid type, MySQL BINARY(16), and SQL Server UNIQUEIDENTIFIER.

  2. Event sourcing and audit logs — Assign a ULID to each event in an event store, message queue (Kafka, Kinesis, SQS), or audit log. The embedded millisecond timestamp gives you a natural ordering key, so you can replay events in creation order or query "everything between two timestamps" by string range alone — no separate created_at index required.

  3. Distributed tracing and correlation IDs — Use ULIDs as request IDs across microservices. The timestamp prefix lets ops engineers eyeball the age of an ID in a log line ("starts with 01HD..., that's recent") without parsing it, and the lexicographic sort makes log aggregators sort trace events correctly even when clocks drift slightly between nodes.

  4. Cursor-based pagination — When you need a stable, sort-friendly cursor for paginating API results, ULIDs work better than offset pagination (which breaks under concurrent inserts) and better than created_at + id composite cursors (which need two columns). Pass the last seen ULID as the ?after= cursor; the next page is WHERE id > :cursor ORDER BY id LIMIT n.

  5. Test fixtures and seed data — Generate batches of ULIDs for integration tests, load-test scripts, or development database seeds. Unlike sequential integers, ULIDs are unique across runs, so reseeding a dev database does not collide with leftover state from a previous run.

  6. Idempotency keys and dedup tokens — Assign a ULID at request creation time and use it as the idempotency key for payment APIs, webhook delivery, or job queue dedup. The 80 bits of randomness make replay attacks impractical, and the timestamp prefix gives you a free TTL signal — drop the key after N days by comparing the embedded timestamp.

Technical Details

XConvert's ULID Generator follows the ulid/spec reference layout exactly: 48 bits of Unix time in milliseconds (MSB-first), then 80 bits of randomness sourced from the browser's crypto.getRandomValues() (the Web Crypto CSPRNG), then the 16-byte big-endian payload encoded to 26 characters using the Crockford Base32 alphabet. The first character is always one of 0 through 7 because the 48-bit timestamp only needs 48 of the 50 bits that 10 Base32 characters can represent — the top 2 bits of the leading character are always zero today, and they stay zero until the year 10889 AD when the timestamp would exceed 2^48 - 1.

Monotonic mode follows the spec algorithm precisely. The generator remembers the last (timestamp, random) pair it produced; if the next generation happens within the same millisecond, the 80-bit random tail is incremented by one (with carry into the upper bytes) instead of being regenerated. If the increment would overflow 2^80 - 1 within a single millisecond — which would require generating more than 1.2 × 10^24 ULIDs in 1 ms — the spec mandates that the generator raise an error rather than silently roll over. In practice, no real workload approaches this limit.

All randomness is sourced from the Web Crypto API's crypto.getRandomValues(), which is backed by the operating system CSPRNG (/dev/urandom on Linux/macOS, BCryptGenRandom on Windows, getentropy on iOS). Bulk generation issues a single getRandomValues() call sized to cover every ULID in the batch, then slices the buffer in 10-byte chunks per ULID — measurably faster than calling the API once per ULID. Generation, encoding, and rendering all happen client-side; your ULIDs are never sent to any server, which matters when they are used as session tokens, idempotency keys, or other secrets.

Tips for Best Results

  1. Default to ULID over UUID v4 for new tables — If you are designing a new schema, ULID gives you all the coordination-free benefits of UUID v4 plus time-ordering for free. The only reason to stick with UUID v4 is if you already have ecosystem tooling (ORMs, validators) that assumes the RFC 4122 version/variant bits — and even then, UUID v7 is now the better choice on the UUID side.

  2. Store as 16-byte binary, not as the 26-char string — Storing ULIDs as BINARY(16) or PostgreSQL uuid saves ~60% versus storing the 26-char Crockford representation. The Crockford string is for humans; the binary is for the index. Convert at the application layer.

  3. Use monotonic mode when generating many IDs in a tight loop — If you are emitting hundreds of events per millisecond from a single process, enable monotonic mode so the order in which you emitted them is preserved in the index. Without it, two ULIDs from the same millisecond sort by their independent random tails, which is effectively random.

  4. Do not parse the timestamp for security decisions — The embedded timestamp is in clear text and can be read by anyone with the ULID. Treat the timestamp as observable information; if you need creation time to be private, do not use ULIDs (or UUID v7, or KSUIDs) for the public-facing identifier.

  5. Watch out for clock skew across nodes — ULIDs sort by the timestamp the generator's clock saw. If two nodes have clocks 50 ms apart, their ULIDs interleave incorrectly in the global sort order by up to 50 ms. NTP keeps most fleets within a few ms; for stricter ordering, generate ULIDs centrally or use a Snowflake-style scheme with a coordinated epoch.

  6. Pair with /convert-timestamp-to-date to decode the prefix — The first 10 characters of a ULID are the Crockford Base32 encoding of the Unix timestamp in milliseconds. Decode them back to a Unix millisecond value, then pass that value through XConvert's timestamp-to-date converter to get a human-readable date. For different ID needs see XConvert's UUID v4 Generator.

Frequently Asked Questions

ULID vs UUID v7 — which should I use?

They are nearly identical in design: both are 128-bit, both embed a 48-bit Unix millisecond timestamp in the high bits, both are lexicographically sortable. The differences are: (1) ULID encodes to 26 Crockford Base32 characters while UUID v7 encodes to the 36-character 8-4-4-4-12 hex format defined by RFC 4122 / RFC 9562; (2) UUID v7 spends 4 bits on the version marker and 2 bits on the variant bits, leaving roughly 74 bits of randomness versus ULID's full 80; (3) UUID v7 is now an IETF standard (RFC 9562, May 2024), while ULID's canonical spec lives at github.com/ulid/spec. Pick UUID v7 if you need ecosystem compatibility with UUID tooling and validators. Pick ULID if you want a more compact string or are already standardized on Crockford Base32 elsewhere.

How sortable are ULIDs really?

Strictly sortable to millisecond precision. Two ULIDs generated in different milliseconds sort by their timestamps under any byte-wise, string, or memcmp comparison — this is true whether you sort the 26-character Crockford string, the 16-byte binary representation, or the value stored in a uuid column. Two ULIDs generated in the same millisecond sort by their 80-bit random tails, which is effectively random — unless you use monotonic mode, in which case the second and subsequent ULIDs in that millisecond are guaranteed to sort after the first.

Why exactly 26 characters?

A 128-bit value encoded in Base32 (5 bits per character) needs ceil(128/5) = 26 characters. The 26th character carries only 3 information bits, and the leading character carries only 6 information bits — the other 2 bits of the leading character are always zero today because the 48-bit timestamp's high bits are unused until the year 10889 AD. That is why every ULID generated today starts with a character in the range 0–7 (Crockford Base32 indices 0–7).

What is the timestamp resolution?

One millisecond. The 48-bit timestamp is the number of milliseconds since the Unix epoch (1970-01-01T00:00:00Z), giving roughly 281 trillion distinct values before rolling over in the year 10889 AD. Sub-millisecond ordering is not part of the spec — that is what the random component (or monotonic mode) is for.

What happens when I generate two ULIDs in the same millisecond?

In the default (non-monotonic) mode, each ULID gets a fresh 80-bit random tail, so they have identical 10-character timestamp prefixes but different 16-character random suffixes. Their sort order within that millisecond is effectively random. In monotonic mode, the spec mandates that the second ULID's random tail is the first one's tail plus 1 (with carry), so they sort in generation order. Monotonic mode fails (raises an error) only if you try to generate more than 2^80 ULIDs within a single millisecond — a limit no real workload reaches.

Are ULIDs compatible with UUID columns in PostgreSQL or MySQL?

Yes. Both are 128 bits, so a ULID drops straight into a PostgreSQL uuid column or a MySQL BINARY(16) column at the binary level. You only need an application-layer codec to convert between the binary 16 bytes and the human-readable 26-character Crockford string. Most ULID libraries (ulid on npm, python-ulid on PyPI, oklog/ulid in Go) ship with helpers for this conversion. Storing the 26-character string in a VARCHAR(26) works but wastes about 60% of the disk space versus binary storage.

Are these ULIDs sent to a server?

No. Generation happens entirely in your browser using crypto.getRandomValues(). The ULIDs never leave the page, are not logged, and are not transmitted to XConvert or any third party. This matters because ULIDs are often used as idempotency keys, session tokens, or other values that must remain confidential.

Can I decode the timestamp from a ULID I already have?

Yes. Take the first 10 characters, decode them as a Crockford Base32 number (5 bits each, 50 bits total — the top 2 bits are always zero), and you have the Unix millisecond timestamp the ULID was generated at. Most ULID libraries expose this as ulid.decodeTime(id) or similar. You can then feed that millisecond value into XConvert's timestamp-to-date converter for a human-readable date.

Is the ULID spec stable?

Yes. The canonical specification at github.com/ulid/spec has been stable since 2017 and has not changed in any binary-breaking way. The 1.0 layout — 48-bit timestamp, 80-bit randomness, 26-character Crockford Base32 — is what every mainstream implementation uses. UUID v7 (RFC 9562) was published in May 2024 and is a different identifier; it does not supersede ULID.

Related Generate tools
Nanoid GeneratorKsuid GeneratorFake Name GeneratorFake Email GeneratorFake Address GeneratorFake Phone GeneratorRandom IpRandom String

Image Tools

Image CompressorCompress JPEGCompress PNGCompress GIFCompress WebPImage ConverterJPG ConverterImage Resizer

Video Tools

Video CompressorCompress MP4MP4 to GIFVideo to GIFVideo ConverterMP4 ConverterVideo Cutter

Audio Tools

Audio CompressorCompress MP3Compress WAVAudio ConverterMP3 ConverterFLAC to MP3Audio Cutter

Document Tools

Compress PDFMerge Images to PDFSplit PDFPDF to JPGUnzip FilesRAR Extractor
© 2026 XConvert.com. All Rights Reserved.
About UsPrivacy PolicyTerms of ServiceContactHelp Us Grow