Ulid
A .NET C# library for generating and working with Universally Unique Lexicographically Sortable Identifiers (ULIDs), designed to be globally unique, sortable, human-readable, and AoT compatible, making them ideal for use in distributed systems and databases.
Install / Use
/learn @ByteAether/UlidREADME
A high-performance, fully compliant .NET implementation of ULIDs (Universally Unique Lexicographically Sortable Identifiers), adhering to the official ULID specification.
Table of Contents
- Introduction
- Features
- Installation
- Usage
- API
- Integration with Other Libraries
- Benchmarking
- Prior Art
- Contributing
- License
Introduction
<img align="right" width="100px" src="assets/logo.png" />ULIDs are universally unique, lexicographically sortable identifiers, ideal for distributed systems and time-ordered data due to their sortability and human-readability—advantages GUIDs lack. This library offers a robust, fully compliant .NET implementation, addressing limitations found in other ULID solutions.
This implementation addresses a potential OverflowException that can occur when generating multiple ULIDs within the same millisecond due to the "random" part overflowing. To ensure dependable, unique ULID generation, our solution increments the timestamp component upon random part overflow, eliminating such exceptions. This behavior aligns with discussions in ULID specification issue #39.
This library uniquely addresses the predictability of monotonic ULIDs generated within the same millisecond by allowing random increments to the random component. This mitigates enumeration attack vulnerabilities, as discussed in ULID specification issue #105. You can configure the random increment with a random value ranging from 1-byte (1–256) to 4-bytes (1–4,294,967,296), enhancing randomness while preserving lexicographical sortability.
ULID vs UUIDv7
In the evolution of distributed identifiers, ULIDs represent the definitive successor to both legacy GUIDs and auto-incrementing integers. While modern standards like UUIDv7 attempt to address sortability, the RFC 9562 makes monotonicity optional, allowing implementations (such as the native .NET provider) to sacrifice strict ordering during sub-millisecond bursts. This "lazy" approach reintroduces the very index fragmentation and out-of-order writes that sortable IDs were meant to solve.
ULID addresses this by design, mandating strict lexicographical sortability and monotonic increments. By enforcing these requirements at the specification level rather than leaving them to the implementor's discretion, ULID ensures consistent, high-performance behavior across all environments. This library provides a robust, compliant implementation that guarantees this order, enabling your application to scale without the performance trade-offs of non-deterministic identifiers.
Features
- Universally Unique: Ensures global uniqueness across systems.
- Sortable: Lexicographically ordered for time-based sorting.
- Lock-Free Synchronization: Monotonic generation utilizes a high-performance, lock-free compare-and-exchange (CAS) approach.
- Specification-Compliant: Fully adheres to the ULID specification.
- Interoperable: Includes conversion methods to and from GUIDs, Crockford's Base32 strings, and byte arrays.
- Ahead-of-Time (AoT) Compilation Compatible: Fully compatible with AoT compilation for improved startup performance and smaller binary sizes.
- Error-Free Generation: Prevents
OverflowExceptionby incrementing the timestamp component when the random part overflows, ensuring continuous unique ULID generation.
These features collectively make ByteAether.Ulid a robust and efficient choice for managing unique identifiers in your .NET applications.
Installation
Install the latest stable package via NuGet:
dotnet add package ByteAether.Ulid
To install a specific preview version, use the --version option:
dotnet add package ByteAether.Ulid --version <VERSION_NUMBER>
Usage
Here is a basic example of how to use the ULID implementation:
using System;
using ByteAether.Ulid;
// Create a new ULID
var ulid = Ulid.New();
// Convert to byte array and back
byte[] byteArray = ulid.ToByteArray();
var ulidFromByteArray = Ulid.New(byteArray);
// Convert to GUID and back
Guid guid = ulid.ToGuid();
var ulidFromGuid = Ulid.New(guid);
// Convert to string and back
string ulidString = ulid.ToString();
var ulidFromString = Ulid.Parse(ulidString);
Console.WriteLine($"ULID: {ulid}, GUID: {guid}, String: {ulidString}");
Filtering by Time Range (LINQ)
Since ULIDs are lexicographically sortable and contain a timestamp, you can use Ulid.MinAt() and Ulid.MaxAt() to generate boundary ULIDs for a specific time range. This allows EF Core to translate these into efficient range comparisons (e.g., WHERE Id >= @min AND Id <= @max) in your database.
public async Task<List<Entity>> GetEntitiesFromYesterday(MyDbContext context)
{
var startOfYesterday = DateTimeOffset.UtcNow.AddDays(-1).Date;
var endOfYesterday = startOfYesterday.AddDays(1).AddTicks(-1);
// Create boundary ULIDs for the time range
var minUlid = Ulid.MinAt(startOfYesterday);
var maxUlid = Ulid.MaxAt(endOfYesterday);
// This query uses the primary key index for high performance
return await context.Entities
.Where(e => e.Id >= minUlid && e.Id <= maxUlid)
.ToListAsync();
}
Advanced Generation
You can customize ULID generation by providing GenerationOptions. This allows you to control monotonicity and the source of randomness.
Example: Monotonic ULID with Random Increments
To generate ULIDs that are monotonically increasing with a random increment, you can specify the Monotonicity option.
using System;
using ByteAether.Ulid;
using static ByteAether.Ulid.Ulid.GenerationOptions;
// Configure options for a 2-byte random increment
var options = new Ulid.GenerationOptions
{
Monotonicity = MonotonicityOptions.MonotonicRandom2Byte
};
// Generate a ULID with the specified options
var ulid = Ulid.New(options);
Console.WriteLine($"ULID with random increment: {ulid}");
Example: Setting Default Generation Options
You can set default generation options for the entire application. This is useful for consistently applying specific behaviors, such as prioritizing performance over cryptographic security.
using System;
using ByteAether.Ulid;
using static ByteAether.Ulid.Ulid.GenerationOptions;
// Set default generation options for the entire application
Ulid.DefaultGenerationOptions = new()
{
Monotonicity = MonotonicityOptions.MonotonicIncrement,
InitialRandomSource = new PseudoRandomProvider(),
IncrementRandomSource = new PseudoRandomProvider()
};
// Now, any subsequent call to Ulid.New() will use these options
var ulid = Ulid.New();
Console.WriteLine($"ULID from pseudo-random source: {ulid}");
API
The Ulid implementation provides the following properties and methods:
Creation
Ulid.New(GenerationOptions? options = null)
Generates a new ULID using default generation options. Accepts an optionalGenerationOptionsparameter to customize the generation behavior.Ulid.New(DateTimeOffset dateTimeOffset, GenerationOptions? options = null)
Generates a new ULID using the specifiedDateTimeOffsetand default generation options. Accepts an optionalGenerationOptionsparameter to customize the generation behavior.Ulid.New(long timestamp, GenerationOptions? options = null)
Generates a new ULID using the specified Unix timestamp in milliseconds (long) and default generation options. Accepts an optionalGenerationOptionsparameter to customize the generation behavior.Ulid.New(DateTimeOffset dateTimeOffset, ReadOnlySpan<byte> random)
Generates a new ULID using the specifiedDateTimeOffsetand a pre-existing random byte array.- `Ulid.New(long ti
Related Skills
feishu-drive
339.5k|
things-mac
339.5kManage Things 3 via the `things` CLI on macOS (add/update projects+todos via URL scheme; read/search/list from the local Things database)
clawhub
339.5kUse the ClawHub CLI to search, install, update, and publish agent skills from clawhub.com
yu-ai-agent
2.0k编程导航 2025 年 AI 开发实战新项目,基于 Spring Boot 3 + Java 21 + Spring AI 构建 AI 恋爱大师应用和 ReAct 模式自主规划智能体YuManus,覆盖 AI 大模型接入、Spring AI 核心特性、Prompt 工程和优化、RAG 检索增强、向量数据库、Tool Calling 工具调用、MCP 模型上下文协议、AI Agent 开发(Manas Java 实现)、Cursor AI 工具等核心知识。用一套教程将程序员必知必会的 AI 技术一网打尽,帮你成为 AI 时代企业的香饽饽,给你的简历和求职大幅增加竞争力。

