![]() |
VOOZH | about |
dotnet add package SequentialGuid --version 6.2.0
NuGet\Install-Package SequentialGuid -Version 6.2.0
<PackageReference Include="SequentialGuid" Version="6.2.0" />
<PackageVersion Include="SequentialGuid" Version="6.2.0" />Directory.Packages.props
<PackageReference Include="SequentialGuid" />Project file
paket add SequentialGuid --version 6.2.0
#r "nuget: SequentialGuid, 6.2.0"
#:package SequentialGuid@6.2.0
#addin nuget:?package=SequentialGuid&version=6.2.0Install as a Cake Addin
#tool nuget:?package=SequentialGuid&version=6.2.0Install as a Cake Tool
๐ Continuous Integration
๐ NuGet
๐ NuGet Downloads
๐ License: MIT
Generate database-friendly, time-ordered UUIDs anywhere in your stack โ no database round-trip required.
SequentialGuid is a zero-dependency .NET library that produces RFC 9562 compliant UUIDs. Generate IDs in Blazor WebAssembly, MAUI, a background worker, or a REST controller โ then pass them through your API and into the database. Because the timestamp is embedded in the value itself, you get natural sort order (dramatically reducing clustered index fragmentation), built-in timestamp extraction (no extra CreatedAt column needed), and client-side idempotency (retry-safe inserts without a server round-trip to generate a key).
Guid.NewGuid()?Guid.NewGuid() produces random version 4 UUIDs. They work, but they fragment clustered indexes in SQL Server, PostgreSQL, and other B-tree based stores because every insert lands at a random page. SequentialGuid solves this by putting the timestamp first โ new rows always append near the end of the index, just like an auto-increment integer, while still giving you the global uniqueness and merge-safety of a UUID.
| Class | RFC 9562 Section | Purpose |
|---|---|---|
GuidV4 |
ยง5.4 | Cryptographically random UUID โ drop-in replacement for Guid.NewGuid() with guaranteed RFC 9562 version & variant bits |
GuidV5 |
ยง5.5 | Deterministic, namespace + name UUID using SHA-1 hashing |
GuidV7 |
ยง5.7 | Time-ordered UUID โ 48-bit Unix millisecond timestamp + 26-bit monotonic counter (ยง6.2 Method 1) + 36 bits of cryptographic randomness |
GuidV8Time |
Appendix B.1 | Time-ordered UUID โ 60-bit .NET Ticks (100 ns precision) + machine/process fingerprint + 22-bit monotonic counter |
GuidV8Name |
Appendix B.2 | Deterministic, namespace + name UUID using SHA-256 hashing |
GuidV7 and GuidV8Time both use a process-global Interlocked.Increment counter so IDs generated on the same timestamp are still strictly ordered, even under heavy concurrencystackalloc, Span<T>, and [SkipLocalsInit] eliminate heap allocations on every generation path on the package's .NET 10 / 9 / 8 targets, including the deterministic v5/v8 name-based generatorsbrowser platform support and Native AOT compatibility for Blazor WebAssemblyIsAotCompatible=true and is verified end-to-end with a published AOT smoke test in CI.ToDateTime() on any Guid (V7, V8, or legacy) to recover the embedded UTC timestamp โ works on SqlGuid tooNewSqlGuid() and .ToSqlGuid() / .FromSqlGuid() handle the byte-order shuffle so your UUIDs sort chronologically in uniqueidentifier columns โ the only production use of System.Data.SqlTypes.SqlGuid is inside SequentialSqlGuid.CompareTo, where it implements SQL Server's documented sort orderBoth generate time-ordered, sortable UUIDs. The difference is timestamp resolution and payload:
GuidV7 |
GuidV8Time |
|
|---|---|---|
| Timestamp precision | 1 ms (Unix Epoch millis) | 100 ns (.NET Ticks) |
| Counter bits | 26-bit monotonic | 22-bit monotonic |
| Random / identity bits | 36 bits of crypto-random data | 40-bit machine + process fingerprint |
| Interoperability | โ Standard UUIDv7 โ understood by any RFC 9562 implementation | .NET-specific custom layout |
| Best for | Cross-platform / polyglot systems, general-purpose use | .NET-only systems that need sub-millisecond ordering or machine traceability |
Rule of thumb: Start with GuidV7. Reach for GuidV8Time only when you need tick-level precision or the machine/process fingerprint.
Both produce deterministic UUIDs from a namespace + name pair. The only difference is the hash algorithm:
GuidV5 โ Uses SHA-1 as required by RFC 9562 ยง5.5. Choose this when you need interoperability with UUIDv5 implementations in other languages.GuidV8Name โ Uses SHA-256 as described in RFC 9562 Appendix B.2, providing a stronger hash for .NET-only scenarios.dotnet add package SequentialGuid
using SequentialGuid;
// Millisecond precision (RFC 9562 UUIDv7) โ recommended for most applications
var id = GuidV7.NewGuid();
// Sub-millisecond / tick precision (RFC 9562 UUIDv8)
var id = GuidV8Time.NewGuid();
Both time-based generators provide a NewSqlGuid() method that rearranges the byte order to match SQL Server's uniqueidentifier sorting rules:
var sqlId = GuidV7.NewSqlGuid();
// or
var sqlId = GuidV8Time.NewSqlGuid();
// Guaranteed RFC 9562 version & variant bits (unlike Guid.NewGuid() on some runtimes)
var id = GuidV4.NewGuid();
// SHA-1 (UUIDv5) โ interoperable with other languages
var id = GuidV5.Create(GuidV5.Namespaces.Url, "https://example.com");
// SHA-256 (UUIDv8 name-based) โ stronger hash, .NET only
var id = GuidV8Name.Create(GuidV8Name.Namespaces.Url, "https://example.com");
DateTime? created = id.ToDateTime();
// Works on GuidV7, GuidV8Time, legacy SequentialGuid, and even SqlGuid values
// Try-pattern variant โ useful when you want to branch without nullable handling
if (id.TryToDateTime(out var created))
{
Console.WriteLine($"Created at {created:O}");
}
// DateTimeOffset variant โ explicit UTC offset
DateTimeOffset? createdOffset = id.ToDateTimeOffset();
// Predicate โ "is this a recognised sequential GUID at all?"
bool isOurs = someGuid.IsSequentialGuid();
// RFC 9562 ยง5.10 max UUID constant โ useful for range-scan upper bounds
Guid upper = Guid.MaxValue;
var guid = GuidV7.NewGuid();
var sqlGuid = guid.ToSqlGuid(); // reorder bytes for SQL Server
var back = sqlGuid.FromSqlGuid(); // restore standard byte order
var id = GuidV7.NewGuid(DateTimeOffset.UtcNow);
var id = GuidV8Time.NewGuid(DateTime.UtcNow);
public interface IIdGenerator
{
Guid NewId();
}
public class SequentialIdGenerator : IIdGenerator
{
public Guid NewId() => GuidV7.NewGuid();
}
// In your startup / Program.cs
services.AddTransient<IIdGenerator, SequentialIdGenerator>();
public abstract class BaseEntity
{
// ID is assigned at construction โ no database round-trip needed
public Guid Id { get; set; } = GuidV7.NewGuid();
// Timestamp is always available โ no extra column required
public DateTime? CreatedAt => Id.ToDateTime();
}
SQL Server sorts uniqueidentifier values in a non-obvious byte order. If you use SQL Server, read these two articles to understand the implications:
Use the NewSqlGuid() methods (or the .ToSqlGuid() extension) to produce UUIDs whose byte order aligns with SQL Server's comparison logic. The .FromSqlGuid() extension on Guid reverses the transformation โ the name clearly conveys the intent of converting from SQL Server byte order back to the standard layout.
The library ships two readonly record struct types โ SequentialGuid and SequentialSqlGuid โ that wrap a Guid and guarantee at construction time that the value is a valid sequential UUID. They both implement ISequentialGuid<TSelf> which provides IComparable, IComparable<TSelf>, IEquatable<TSelf>, IFormattable / ISpanFormattable / ISpanParsable<T> / IUtf8SpanFormattable / IUtf8SpanParsable<T> (where available), and comparison operators.
| Struct | Byte Order | Use When |
|---|---|---|
SequentialGuid |
Standard (RFC) | Your database uses standard GUID sorting (PostgreSQL, MySQL, SQLite, Cosmos DB, MongoDB, etc.) |
SequentialSqlGuid |
SQL Server | Your database is SQL Server, which sorts uniqueidentifier in a non-obvious byte order |
using SequentialGuid;
// Generate a new V7 UUID (default)
var id = new SequentialGuid();
// Generate a new V8 UUID
var id = new SequentialGuid(SequentialGuidType.Rfc9562V8Custom);
// Wrap an existing Guid (validates it is a sequential UUID)
var id = new SequentialGuid(existingGuid);
// Parse from a string
var id = new SequentialGuid("01234567-89ab-7def-8000-0123456789ab");
SQL Server variant:
var sqlId = new SequentialSqlGuid();
var sqlId = new SequentialSqlGuid(SequentialGuidType.Rfc9562V8Custom);
var sqlId = new SequentialSqlGuid(existingGuid); // auto-detects byte order
Guid raw = id.Value; // the underlying Guid
DateTime utc = id.Timestamp; // the embedded UTC timestamp
The structs support <, <=, >, >=, ==, and != operators, plus CompareTo and Equals:
var a = new SequentialGuid();
var b = new SequentialGuid();
bool isNewer = b > a; // true โ b was created after a
// Also comparable directly against Guid
bool same = a.Equals(a.Value); // true
On .NET 7+ the library includes built-in JsonConverter<T> support. Register the converters once:
using SequentialGuid.Extensions;
var options = new JsonSerializerOptions();
options.AddSequentialGuidConverters();
// Now SequentialGuid / SequentialSqlGuid serialize as GUID strings automatically
var json = JsonSerializer.Serialize(new SequentialGuid(), options);
// Parse (throws on invalid input)
var id = SequentialGuid.Parse("01234567-89ab-7def-8000-0123456789ab");
// TryParse (returns false on invalid input)
if (SequentialGuid.TryParse(input, out var parsed))
{
// use parsed
}
| Package | Purpose | Docs |
|---|---|---|
| SequentialGuid.EntityFrameworkCore | Value converters so EF Core can persist SequentialGuid / SequentialSqlGuid properties as Guid columns |
|
| SequentialGuid.MongoDB | Drop-in IIdGenerator + BSON serializers for the MongoDB C# driver |
|
| SequentialGuid.NodaTime | Extension methods for Instant, OffsetDateTime, and ZonedDateTime โ generate and extract timestamps using NodaTime types |
On modern .NET the hot paths are zero-allocation โ byte buffers use stackalloc and Span<T>, and conversion methods are annotated with [SkipLocalsInit]. A BenchmarkDotNet project is included under util/Benchmarks so you can verify on your own hardware:
cd util/Benchmarks
dotnet run -c Release -- --filter *Generation*
The new RFC 9562 algorithm is fully backwards compatible with previously generated Guids:
ToDateTime() extension method can extract timestamps from both legacy and new UUIDs, so you do not need to migrate existing data.| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net6.0 net6.0 was computed. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 is compatible. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. net11.0 net11.0 is compatible. |
| .NET Core | netcoreapp2.0 netcoreapp2.0 was computed. netcoreapp2.1 netcoreapp2.1 was computed. netcoreapp2.2 netcoreapp2.2 was computed. netcoreapp3.0 netcoreapp3.0 was computed. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 netstandard2.0 is compatible. netstandard2.1 netstandard2.1 was computed. |
| .NET Framework | net461 net461 was computed. net462 net462 is compatible. net463 net463 was computed. net47 net47 was computed. net471 net471 was computed. net472 net472 was computed. net48 net48 was computed. net481 net481 was computed. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen40 tizen40 was computed. tizen60 tizen60 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
Showing the top 5 NuGet packages that depend on SequentialGuid:
| Package | Downloads |
|---|---|
|
SequentialGuid.NodaTime
Provide extension methods to round trip between NodaTime Instant and sequential guid |
|
|
BR.MicroServices.Utilities
Package Description |
|
|
Loyo.EntityFramework
EntityFrameworkCore UnitOfWork Repositories |
|
|
Atomiv.Infrastructure.SequentialGuid
Package Description |
|
|
Freakout.MsSql
Package Description |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 6.2.0 | 696 | 6/10/2026 |
| 6.1.0 | 3,413 | 5/13/2026 |
| 6.0.0 | 640 | 5/12/2026 |
| 5.0.7 | 8,843 | 3/21/2026 |
| 5.0.6 | 532 | 3/18/2026 |
| 5.0.5 | 247 | 3/17/2026 |
| 5.0.4 | 6,749 | 3/17/2026 |
| 5.0.3 | 5,030 | 3/13/2026 |
| 5.0.2 | 3,471 | 3/9/2026 |
| 4.0.6 | 215,393 | 2/19/2025 |
| 4.0.5 | 210,338 | 3/20/2024 |
| 4.0.4 | 466,856 | 2/27/2023 |
| 4.0.3 | 50,768 | 10/25/2022 |
| 4.0.2 | 9,650 | 10/20/2022 |
| 4.0.1 | 5,907 | 10/10/2022 |
| 4.0.0 | 4,555 | 10/5/2022 |
| 3.0.1 | 129,220 | 2/22/2022 |
| 3.0.0 | 39,949 | 9/15/2021 |