Skip to content

A small, allocation-conscious, thread-safe .NET utility for generating name-based deterministic UUIDs (a.k.a. GUIDs) using RFC 4122 version 3 (MD5) and version 5 (SHA-1).

License

Notifications You must be signed in to change notification settings

bgrainger/DeterministicGuids

 
 

Repository files navigation

DeterministicGuids DeterministicGuids

GitHub Workflow Status NuGet NuGet Codacy Grade Codecov

A small, allocation-conscious, thread-safe .NET utility for generating name-based deterministic UUIDs (a.k.a. GUIDs) using RFC 4122 version 3 (MD5) and version 5 (SHA-1).

You give it:

  • a namespace GUID (for a logical domain like "Orders", "Users", "Events")
  • a name (string within that namespace)
  • and (optionally) the UUID version (3 or 5).
    If you don't specify it, it defaults to version 5 (SHA-1).

It will always return the same GUID for the same (namespace, name, version) triplet.

This is useful for:

  • Stable IDs across services or deployments
  • Idempotent commands / events
  • Importing external data but keeping predictable identifiers
  • Deriving IDs from business keys without storing a lookup table

Features

  • Deterministic
    Same (namespace, name, version) → same output every time.

  • Standards-based
    Implements RFC 4122 §4.3 for UUIDv3 (MD5-based) and UUIDv5 (SHA-1-based).

  • Thread-safe
    No shared mutable state, no static caches, no locks. You can call it from many threads at once.

  • Optimized memory profile

    • Uses Span<byte> and stackalloc for fixed-size work.
    • Uses ArrayPool<byte> for variable-length buffers (the UTF-8 input string), instead of allocating on every call.
    • Uses incremental hashing on modern runtimes, so we never build a giant namespace+name concatenated array.
  • Zero runtime GUID parsing for known namespaces
    Namespaces are defined using the numeric Guid constructor, not Guid.Parse(...), so there is no string parsing cost at first use.

  • Multi-targeted

    • netstandard2.0
    • netstandard2.1
    • net8.0 (and above)

On newer targets we take advantage of newer BCL APIs to reduce allocations to near zero.

Quick Start

using DeterministicGuids;

// Choose a namespace (either one of the built-ins or your own Guid)
var ns = DeterministicGuid.Namespaces.Events;

// Define the stable name/key within that namespace
var key = "order:12345";

// Generate a deterministic GUID.
// This uses version 5 (SHA-1) by default.
Guid idV5 = DeterministicGuid.Create(ns, key);

Console.WriteLine(idV5);
// Same ns + key + version (5) will always produce the same Guid

Benchmarks

DeterministicGuids stacks very well against other libraries in terms of speed and memory usage. Here are some benchmarks with values taken directly from a run in GitHub Actions.

Method Mean Error StdDev Ratio RatioSD Gen0 Allocated Alloc Ratio
DeterministicGuids 596.3 us 6.56 us 5.81 us 1.00 0.01 - 2.22 KB 1.00
Be.Vlaanderen.Basisregisters.Generators.Guid.Deterministic 975.9 us 19.32 us 35.82 us 1.64 0.06 48.8281 1236.92 KB 557.24
UUIDNext 662.0 us 9.61 us 7.51 us 1.11 0.02 38.0859 939.76 KB 423.37

Credits

Check out our list of contributors!

About

A small, allocation-conscious, thread-safe .NET utility for generating name-based deterministic UUIDs (a.k.a. GUIDs) using RFC 4122 version 3 (MD5) and version 5 (SHA-1).

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 100.0%