Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ulid

Go Report Card Go Reference License: MIT

A lightweight, stateless implementation of ULIDs (Universally Unique Lexicographically Sortable Identifiers) for Go.

Minimal overhead, zero external dependencies, and full control over entropy sources. Encode in 26-character Base32 strings that are naturally sortable and human-readable.


What is a ULID?

A ULID is a 128-bit identifier composed of:

  • 48-bit timestamp (millisecond precision, sortable by creation time)
  • 80-bit entropy (random component, ensures uniqueness)

This makes ULIDs perfect for database IDs, request tracing, and anywhere you need sortable unique identifiers.

01ARZ3NDEKTSV4RRFFQ69G5FAV
│                         │
└─ 10-char timestamp      └─ 16-char entropy (in Base32)

Quick Start

Simple Generation

package main

import (
	"fmt"
	"lowbit.dev/ulid"
)

func main() {
	id := ulid.Make()
	fmt.Println(id) // e.g., 01ARZ3NDEKTSV4RRFFQ69G5FAV
	fmt.Println(id.Time()) // Timestamp of generation
}

Parsing

id, err := ulid.Parse("01ARZ3NDEKTSV4RRFFQ69G5FAV")
if err != nil {
	log.Fatal(err)
}
fmt.Println(id.Time())

Custom Entropy Source

For deterministic testing or custom randomness:

now := time.Now()
entropy := bytes.NewReader(randomBytes)
id, err := ulid.MakeCustom(now, entropy)

Monotonic Generation

By default, Make() generates random ULIDs. If you need strict lexicographical ordering even for IDs generated in the same millisecond, use MonotonicGenerator:

gen := ulid.NewMonotonic(nil) // nil uses crypto/rand

id1 := gen.Make(time.Now()) // 01ARZ3NDEKTSV4RRFFQ69G5FAV
id2 := gen.Make(time.Now()) // 01ARZ3NDEKTSV4RRFFQ69G5FB0 (entropy incremented)
id3 := gen.Make(time.Now()) // 01ARZ3NDEKTSV4RRFFQ69G5FB1

// id1 < id2 < id3, even if all generated within the same millisecond

The generator maintains internal state and automatically rolls over to fresh entropy when the timestamp advances. If entropy space is exhausted within a millisecond, ErrOverflow is returned.


API Reference

Creating ULIDs

  • Make() ULID — Generate a new ULID using the current time and crypto/rand.
  • MakeCustom(t time.Time, entropy io.Reader) (ULID, error) — Generate a ULID with explicit time and entropy source.

Parsing

  • Parse(s string) (ULID, error) — Parse a 26-character Base32 string into a ULID.
    • Supports Crockford Base32 aliases: O0, I/L1
    • Case-insensitive

Formatting

  • String() string — Format the ULID as a 26-character Base32 string.
  • AppendText(dst []byte) []byte — Zero-allocation append to an existing byte slice.
  • MarshalText() ([]byte, error) — JSON-compatible text marshaling.

Extraction

  • Time() time.Time — Extract the creation timestamp from the ULID.

Monotonic Generation

  • NewMonotonic(entropy io.Reader) *MonotonicGenerator — Create a stateful monotonic generator.
  • MonotonicGenerator.Make(t time.Time) (ULID, error) — Generate a strictly monotonic ULID.

Design

  • Stateless by Default: Make() and MakeCustom() are pure functions. No global state.
  • Explicit Control: You provide the time and entropy source. No hidden syscalls.
  • Zero-Allocation Formatting: AppendText() avoids heap allocations during string conversion.
  • Standard Library Only: No external dependencies. Uses only crypto/rand, io, and time.
  • Lexicographically Sortable: Naturally sorted by timestamp, then by entropy.
  • Human-Readable Encoding: Crockford Base32 with aliases for error tolerance.

Why Monotonic?

In high-throughput scenarios where multiple IDs might be generated in the same millisecond, monotonic generation ensures a guaranteed sort order without relying on wall-clock precision. This is useful for:

  • Distributed event logging
  • High-frequency database inserts
  • Transaction IDs in concurrent systems

Use MonotonicGenerator when you need deterministic ordering, and plain Make() for simplicity when millisecond-level sorting is sufficient.

About

A lightweight, stateless ULID implementation in Go.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages