MIT License Hex Version Hex Downloads

User eXperience focused IDentifiers (UXIDs) are prefixed, K-sortable, Stripe-style identifiers like usr_01epey2p06tr1rtv07xa82zgjj. They are:

  • Descriptive — the prefix names the resource on sight (aids debugging and investigation)
  • Copy/paste friendly — double-clicking selects the entire ID
  • Tunable in size — shortened for low-cardinality resources
  • Secure against enumeration attacks
  • Application-generated — not tied to the datastore
  • K-sortable — lexicographically sortable by time, so they index well
  • Coordination-free — no startup or generation-time coordination required
  • Unlikely to collide — more randomness, lower odds
  • Human-transmissible — easy to read out accurately over the phone
  • Optionally monotonic — a burst within one millisecond stays unique and strictly ordered
  • Optionally governed by a registry — one module keeps every prefix unique and maps an ID back to its resource

Many of the concepts of Stripe IDs have been used in this library.

Installation

Add uxid to your dependencies in mix.exs:

def deps do
  [
    {:uxid, "~> 2.6"}
  ]
end

Ecto is an optional dependency — UXID only pulls it in if your app already uses it.

Quick start

# No options generates a plain ULID
UXID.generate!()                              # "01emdgjf0dqxqj8fm78xe97y3h"

# Add a prefix to name the resource
UXID.generate!(prefix: "cus")                 # "cus_01emdgjf0dqxqj8fm78xe97y3h"

# Shrink the random part for low-cardinality resources
# T-shirt sizes: :xs :s :m :l :xl (or :xsmall :small :medium :large :xlarge)
UXID.generate!(prefix: "cus", size: :small)   # "cus_01eqrh884aqyy1"

# Uppercase to match earlier UXID versions
UXID.generate!(case: :upper)                  # "01EMDGJF0DQXQJ8FM78XE97Y3H"

Ecto in 30 seconds

UXIDs work as Ecto fields, including primary keys — set the field type to UXID and pass the same options you'd pass to generate!/1:

defmodule YourApp.User do
  use Ecto.Schema

  @primary_key {:id, UXID, autogenerate: true, prefix: "usr", size: :medium}
  schema "users" do
    field :api_key, UXID, autogenerate: true, prefix: "apikey", size: :small
  end
end

See the Ecto Integration guide for foreign keys, strict validation, and migrating a uuid column to UXIDs.

Guides

The five-minute path is above; each area has a dedicated guide:

  • Sizes & Encoding — the t-shirt sizes, how much randomness each carries, and compact-time mode for extra collision resistance.
  • Ecto Integration — primary/foreign keys, strict validate: casting, allow_uuid coexistence, and UXID.valid?/2.
  • Monotonic IDs — guaranteed same-millisecond uniqueness and ordering, the security tradeoff, and when to use it.
  • Prefix Registry — a compile-time DSL that keeps every prefix unique, routes an ID back to its schema, works in layered/umbrella apps, and exports a cross-source JSON manifest.
  • Configuration — every config :uxid key in one place, with per-call vs. global precedence.

Documentation

Full API docs are on HexDocs. The registry and routing patterns are drawn from Adam Kirk's ElixirConf US 2025 talk, UXIDs in Elixir/Ecto.

License

UXID is released under the MIT License.