TypeID Specification and CLI

repository·main·Indexed 25 days ago

https://github.com/jetify-com/typeid

A specification for type-safe, K-sortable, globally unique identifiers that extend UUIDv7 with a type prefix. Includes the typeid-cli for generating, encoding, and decoding IDs, as well as detailed format requirements for prefixes and base32 encoding of UUID suffixes.

Tokens
1.8K
Snippets
6
Records
17
Agent score
86%

What's inside TypeID

  1. Understand the TypeID format

    main

    A TypeID is a type-safe, K-sortable, globally unique identifier inspired by Stripe IDs. It is a modern extension of UUIDv7. A TypeID is canonically encoded as a lowercase string consisting of three parts:

    1. Type prefix: At most 63 characters in all lowercase snake_case ASCII ([a-z_]).
    2. Separator: An underscore _.
    3. UUID suffix: A 128-bit UUIDv7 encoded as a 26-character string using a modified base32 encoding.

    Example of a TypeID with the type user: user_2x4y6z8a0b1c2d3e4f5g6h7j8k

    user_2x4y6z8a0b1c2d3e4f5g6h7j8k
    └──┘ └────────────────────────┘
    type    uuid suffix (base32)
  2. Understand the TypeID structure

    main

    A TypeID is a type-safe extension of UUIDv7 that encodes a 128-bit UUID in base32 and adds an optional type prefix. It consists of three parts:

    1. Type Prefix: A string denoting the type (e.g., user). It must be at most 63 characters, lowercase [a-z_], and must start and end with an alphabetic character [a-z].
    2. Separator: An underscore _ used if a prefix is present. It is omitted if the prefix is empty.
    3. UUID Suffix: A 26-character base32 encoded string representing a 128-bit UUIDv7.

    Length Constraints:

    • Minimum length: 26 characters (empty prefix).
    • Maximum length: 90 characters (63-char prefix + 1 separator + 26-char suffix).
  3. Examples of valid and invalid TypeIDs

    main

    Valid Examples

    PrefixExample TypeID
    (empty)01h5fskfsk4fpeqwnsyz5hj55t
    useruser_01h5fskfsk4fpeqwnsyz5hj55t
    my_typemy_type_01h5fskfsk4fpeqwnsyz5hj55t
    my__typemy__type_01h5fskfsk4fpeqwnsyz5hj55t
    a_b_ca_b_c_01h5fskfsk4fpeqwnsyz5hj55t

    Invalid Examples

    Invalid TypeIDReason
    PREFIX_01h5fskfsk4fpeqwnsyz5hj55tPrefix contains uppercase letters
    12345_01h5fskfsk4fpeqwnsyz5hj55tPrefix contains numbers
    _prefix_01h5fskfsk4fpeqwnsyz5hj55tPrefix starts with underscore
    prefix__01h5fskfsk4fpeqwnsyz5hj55tPrefix ends with underscore
    prefix_0123456789ABCDEFGHJKMNPQRSSuffix contains uppercase letters
    prefix_8zzzzzzzzzzzzzzzzzzzzzzzzzSuffix exceeds max value (first char > 7)
  4. Format requirements for TypeID prefixes

    main

    When defining a type prefix for a TypeID, follow these rules:

    • Character Set: Only lowercase alphabetic ASCII [a-z] and underscores _ are allowed. Digits and uppercase letters are prohibited.
    • Length: Maximum 63 characters. It can be empty.
    • Boundary Rules: If not empty, the prefix must start and end with an alphabetic character [a-z]. Underscores are not allowed at the beginning or end.
    • Consecutive Underscores: foo__bar is valid.
    • Best Practice: Use prefixes at least 3 characters long (e.g., usr_ instead of u_) for better scalability.

    Regex for validation: ^([a-z]([a-z_]{0,61}[a-z])?)?$

  5. Base32 encoding details for UUID suffixes

    main

    The UUID suffix encodes 128 bits of data into 26 characters using a specific base32 method:

    1. Bit Preparation: Treat the 128-bit UUID in big-endian order. Prepend two zeroed bits to the left, resulting in 130 bits.
    2. Grouping: Split the 130 bits into 26 groups of 5 bits each.
    3. Alphabet: Use the following lowercase alphabet: 0123456789abcdefghjkmnpqrstvwxyz.

    Critical Validation Rule: Because the first two bits are always zero, the first character of the suffix must never exceed the decimal value 7. Implementations MUST reject any suffix where the first character is greater than 7 (e.g., 8zzzz... is invalid) to prevent overflow beyond 128 bits.

  6. UUIDv7 compatibility requirements

    main

    When generating a TypeID, the encoded UUID suffix must represent a valid UUIDv7. This requires:

    • Version: Bits 48-51 of the UUID must be 0111.
    • Variant: Bits 64-65 of the UUID must be 10.

    Implementations should ideally allow encoding/decoding of other UUID variants (like v1 or v4) if provided by the user, but the specification is centered on v7.

  7. Available TypeID Implementations

    main

    TypeID is a specification (latest version v0.3.0). Several implementations are available across different languages.

    Official Implementations by jetify

    • Go: Implemented (v0.3)
    • SQL: Implemented (v0.2)
    • TypeScript: Implemented (v0.3)

    Community Implementations

    Implementations exist for many other languages including C# (.NET), Dart, Elixir, Erlang, Gleam, Haskell, Java, Kotlin, Lua, OCaml, Odin, PHP, Postgres, Python, Ruby, Rust, Scala, Swift, T-SQL, and Zig. Always check the implementation's spec version compatibility (e.g., v0.2 vs v0.3) before use.

  8. Encode a UUID into a TypeID

    main

    Use the typeid encode command with a prefix and a UUID to convert a standard UUID into a TypeID format.

    $ typeid encode prefix 0188bac7-4afa-78aa-bc3b-bd1eef28d881
    prefix_01h2xcejqtf2nbrexx3vqjhp41
  9. Decode a TypeID into a UUID

    main

    Use the typeid decode command with a prefix to extract the underlying UUID and the type prefix from an existing TypeID.

    $ typeid decode prefix_01h2xcejqtf2nbrexx3vqjhp41
    type: prefix
    uuid: 0188bac7-4afa-78aa-bc3b-bd1eef28d881