KairosId is a high-performance C# library for generating unique, time-ordered identifiers. It is designed to be lightweight, efficient, and easy to use in modern .NET applications.
Tip
What's in a name? The name comes from the ancient Greek word kairos (καιρός), which refers to the "opportune moment" or "the right time"—unlike chronos (χρόνος), which refers to chronological or sequential time. This library is designed to be exactly that: the opportune identifier for your modern .NET applications.
- Time-Ordered: IDs are sortable by creation time (even those generated in the same millisecond).
- Compact: Only 18 characters long in its default Base58 representation.
- High Performance: Built with
readonly structandUInt128(C# 12 / .NET 8) to minimize allocations. - Flexible Formats: Supports Base58, Base32 (Crockford), and Base16 (Hex).
- No Dependencies: Clean, self-contained library.
This library targets .NET 8 and later. You can reference the project directly or build it as a NuGet package.
using KairosId;
// Generate a new ID (current time)
KairosId id = KairosId.NewKairosId();
// Generate an ID for a specific timestamp
var oldId = KairosId.NewKairosId(DateTimeOffset.UtcNow.AddDays(-1));
Console.WriteLine(id); // Output: Base58 string (e.g., "7Yh9S...")// Parse from string (detects format based on length)
KairosId id = KairosId.Parse("7Yh9S6K8L3M2N1P4R5");
// Format to string
string b58 = id.ToString(); // Base58 (18 chars)
string b32 = id.ToBase32(); // Crockford (22 chars)
string hex = id.ToHex(); // Hexadecimal (27 chars)For better domain modeling and type safety, it is highly recommended to wrap KairosId in a readonly record struct. This prevents accidental assignment of different ID types:
public readonly record struct ProductId(KairosId Value)
{
public static ProductId New() => new(KairosId.NewKairosId());
public override string ToString() => Value.ToString();
public static implicit operator KairosId(ProductId id) => id.Value;
}
// Usage
public void ProcessOrder(CustomerId customerId, ProductId productId) { ... }Whether you are just starting or looking for deep technical details, we have you covered:
- API Reference: Explore the public contract, implemented interfaces, and a detailed guide to every method.
- Internal Design: Understand the 105-bit structure, performance optimizations, and the math behind our Base58 encoding.
- Performance: Speed and memory benchmark results.
- Interface: API and usage differences compared to ULID and GUID.
- Implementation: Technical design and data layout differences.
This project uses CSharpier for code formatting and Husky.Net for git hooks.
Before pushing changes, the pre-push hook will automatically check the code formatting and run tests. if the code is not formatted, the push will be interrupted.
The hooks are automatically installed during the build/restore process via MSBuild. You normally don't need to run anything manually.
If you ever need to manually reinstall them:
dotnet tool restore
dotnet husky install- Format code:
make format - Run tests:
make tests - Run benchmarks:
make benchmarks
- Cysharp/Ulid: Served as a vital reference and inspiration for significantly improving the performance of KairosId.
- ByteAether/Ulid: Provided key ideas for the implementation of the monotonicity logic.