by Stan Drapkin
- High-performance, cryptographically strong GUID generation
- Database-optimized GUIDs for SQL Server and PostgreSQL
- RFC 9562 compliant Version 7 UUID generation and extraction
- AWS Lambda SnapStart and VM-Fork cloning mitigation
- Fast random byte filling
- Fastest .NET random string generation
.NET 5.0+support (compatible with older .NET Frameworks)
dotnet add package FastGuidGuid FastGuid.NewGuid()- Returns a cryptographically random GUID.
- ~10x (900%) faster than Guid.NewGuid().
FastGuid.Fill(Span<byte> data)- Fills a span with cryptographically strong random bytes.
- ~1.5x (50%) to 9x (800%) faster for <512 bytes, otherwise calls RandomNumberGenerator.Fill()
-
Guid FastGuid.NewSqlServerGuid()- Returns a new Guid optimized for use as a SQL Server clustered key.
- Guid structure is
[8 random bytes][8 bytes of SQL-Server-ordered DateTime.UtcNow] - Each Guid is sequential across 100-nanosecond
UtcNowprecision limits. - 64-bit cryptographic randomness adds uniqueness for timestamp collisions and provides reasonable unguessability and protection against online brute-force attacks.
-
Guid FastGuid.NewPostgreSqlGuid()- Returns a new Guid optimized for use as a PostgreSQL primary key or index.
- Guid structure is
[8 bytes of PostgreSQL-ordered DateTime.UtcNow][8 random bytes] - Each Guid is sequential across 100-nanosecond
UtcNowprecision limits. - 64-bit cryptographic randomness adds uniqueness for timestamp collisions and provides reasonable unguessability and protection against online brute-force attacks.
-
Helper methods for Guids generated by
NewSqlServerGuid():DateTime FastGuid.SqlServer.GetTimestamp(Guid guid)- Extracts SqlServer Guid creation timestamp (UTC). Full
DateTime.UtcNowprecision.
- Extracts SqlServer Guid creation timestamp (UTC). Full
Guid FastGuid.SqlServer.MinGuidForTimestamp(DateTime timestampUtc)Guid FastGuid.SqlServer.MaxGuidForTimestamp(DateTime timestampUtc)- Return the smallest/largest Guid for a given timestamp (useful for time-based SQL-Server range searches).
-
Helper methods for Guids generated by
NewPostgreSqlGuid():DateTime FastGuid.PostgreSql.GetTimestamp(Guid guid)- Extracts PostgreSQL Guid creation timestamp (UTC). Full
DateTime.UtcNowprecision.
- Extracts PostgreSQL Guid creation timestamp (UTC). Full
Guid FastGuid.PostgreSql.MinGuidForTimestamp(DateTime timestampUtc)Guid FastGuid.PostgreSql.MaxGuidForTimestamp(DateTime timestampUtc)- Return the smallest/largest Guid for a given timestamp (useful for time-based PostgreSQL range searches).
string FastGuid.StringGen.Text16(int length)- Generates a random string using the Base16 (hex) alphabet.
string FastGuid.StringGen.Text32(int length)- Generates a random string using the Base32 alphabet (RFC 4648).
string FastGuid.StringGen.Text32c(int length)- Generates a random string using the Crockford Base32 alphabet.
string FastGuid.StringGen.Text64(int length)- Generates a random string using the Base64 alphabet (RFC 4648).
string FastGuid.StringGen.Text64Url(int length)- Generates a random string using the Base64Url alphabet (RFC 4648, URL-safe).
- All methods use cryptographically strong randomness and are suitable for passwords, tokens, keys, and identifiers.
New fast extension methods for efficient conversion between GUIDs and compact Base64Url strings:
-
string Guid.ToBase64Url()- Converts a Guid to a 22-character Base64Url string (URL-safe, no padding).
- Useful for compact GUID-as-string identifiers in URLs, tokens, or text fields.
-
Guid string.FromBase64Url()- Converts a 22-character Base64Url string back to a Guid.
- Throws
ArgumentExceptionif the input is invalid.
-
bool GuidExtensions.TryFromBase64Url(ReadOnlySpan<char> base64Url, out Guid guid)- Tries to convert a Base64Url string to a Guid.
- Returns
trueif successful,falseotherwise (never throws).
Faster and more capable Version 7 UUID generation than System.Guid.CreateVersion7(), with support for DateTime and DateTimeOffset timestamps, and timestamp extraction.
Guid FastGuid.UUID.CreateVersion7()- Returns an RFC 9562 compliant UUIDv7 with embedded UTC timestamp.
- Faster alternative to
System.Guid.CreateVersion7().
Guid FastGuid.UUID.CreateVersion7(DateTimeOffset timestamp)CreateVersion7(DateTime utcTimestamp)- Generate UUIDv7 pinned to a specific UTC timestamp.
DateTime FastGuid.UUID.ExtractDateTimeV7(Guid guidv7)- Extracts the embedded UTC timestamp out of a valid UUIDv7 with 1-millisecond precision. Throws on invalid formats.
bool FastGuid.UUID.TryExtractDateTimeV7(Guid guidv7, out DateTime timestamp)- Non-throwing UUIDv7 timestamp extraction. Returns
trueif successful.
- Non-throwing UUIDv7 timestamp extraction. Returns
Warning
While compliant with RFC standards, UUIDv7 identifiers generate high data page fragmentation when used as primary/clustered keys inside relational databases. For database keys, use FastGuid.NewSqlServerGuid() or FastGuid.NewPostgreSqlGuid() instead.
In virtualized serverless execution environments like AWS Lambda (SnapStart), micro-VM instances can be snapshot-frozen and cloned across multiple instances simultaneously. If left unmanaged, standard thread-local random buffers could produce identical sequences of identifiers across different machines, causing catastrophic cryptographic collisions.
FastGuid mitigates this entirely using an atomic Global Epoch Verification Pattern.
To guarantee that no pre-snapshot buffered randomness is ever reused after a restore operation, simply trigger FastGuid.Reset() inside your platform's post-restore lifecycle hook:
// Register this action within your AWS Lambda RegisterAfterRestore hook
public void OnAwsSnapStartRestore()
{
SecurityDriven.FastGuid.Reset();
}| API Signature | Description |
|---|---|
Guid FastGuid.NewGuid() |
Returns a cryptographically strong random GUID. |
void FastGuid.Fill(Span<byte> data) |
Fills a span with cryptographically strong random bytes. |
void FastGuid.Reset() |
Invalidates all thread-local buffers (critical for cloud/Lambda VM-fork hooks). |
Guid FastGuid.NewSqlServerGuid() |
Returns a GUID optimized for use as a SQL Server clustered key (uses current UTC timestamp). |
Guid FastGuid.NewSqlServerGuid(DateTime timestampUtc) |
Returns a SQL Server-optimized GUID for a specific UTC timestamp. |
Guid FastGuid.NewPostgreSqlGuid() |
Returns a GUID optimized for use as a PostgreSQL key (uses current UTC timestamp). |
Guid FastGuid.NewPostgreSqlGuid(DateTime timestampUtc) |
Returns a PostgreSQL-optimized GUID for a specific UTC timestamp. |
DateTime FastGuid.SqlServer.GetTimestamp(Guid guid) |
Extracts the creation timestamp (UTC) from a SQL Server GUID. |
Guid FastGuid.SqlServer.MinGuidForTimestamp(DateTime timestampUtc) |
Returns the smallest SQL Server GUID for a given timestamp. |
Guid FastGuid.SqlServer.MaxGuidForTimestamp(DateTime timestampUtc) |
Returns the largest SQL Server GUID for a given timestamp. |
DateTime FastGuid.PostgreSql.GetTimestamp(Guid guid) |
Extracts the creation timestamp (UTC) from a PostgreSQL GUID. |
Guid FastGuid.PostgreSql.MinGuidForTimestamp(DateTime timestampUtc) |
Returns the smallest PostgreSQL GUID for a given timestamp. |
Guid FastGuid.PostgreSql.MaxGuidForTimestamp(DateTime timestampUtc) |
Returns the largest PostgreSQL GUID for a given timestamp. |
Guid FastGuid.UUID.CreateVersion7() |
Returns an RFC 9562 compliant UUIDv7 with an embedded current UTC timestamp. |
Guid FastGuid.UUID.CreateVersion7(DateTimeOffset timestamp) |
Generates an RFC 9562 compliant UUIDv7 pinned to a specific DateTimeOffset. |
Guid FastGuid.UUID.CreateVersion7(DateTime utcTimestamp) |
Generates an RFC 9562 compliant UUIDv7 pinned to a specific UTC DateTime. |
DateTime FastGuid.UUID.ExtractDateTimeV7(Guid guidv7) |
Extracts the embedded UTC timestamp from a valid UUIDv7 (1-ms precision). Throws on error. |
bool FastGuid.UUID.TryExtractDateTimeV7(Guid guidv7, out DateTime timestamp) |
Tries to extract the UTC timestamp from a valid UUIDv7. Returns true if successful. |
string FastGuid.StringGen.Text16(int length) |
Generates a random string using the Base16 (hex) alphabet. |
string FastGuid.StringGen.Text32(int length) |
Generates a random string using the Base32 alphabet (RFC 4648). |
string FastGuid.StringGen.Text32c(int length) |
Generates a random string using the Crockford Base32 alphabet. |
string FastGuid.StringGen.Text64(int length) |
Generates a random string using the Base64 alphabet (RFC 4648). |
string FastGuid.StringGen.Text64Url(int length) |
Generates a random string using the Base64Url alphabet (RFC 4648, URL-safe). |
string Guid.ToBase64Url() (Guid extension) |
Converts a GUID to a 22-character Base64Url string (URL-safe, no padding). |
Guid string.FromBase64Url() (string extension) |
Converts a 22-character Base64Url string back to a GUID. |
bool GuidExtensions.TryFromBase64Url(ReadOnlySpan<char> base64Url, out Guid guid) |
Tries to convert a Base64Url string to a GUID. Returns true if successful, false otherwise. |
Replace all calls to Guid.NewGuid() with FastGuid.NewGuid()
..from this:
Guid guid = Guid.NewGuid(); // your current code..to this:
// using SecurityDriven;
Guid guid = FastGuid.NewGuid(); // 10x faster- Thread-safe
- 128 bits of cryptographically strong randomness
Switch from this:
Span<byte> key = stackalloc byte[32];
RandomNumberGenerator.Fill(key); // 145 nanoseconds..to this:
Span<byte> key = stackalloc byte[32];
FastGuid.Fill(key); // 20 nanoseconds (7x faster)Important
Guid.CreateVersion7()
causes page-fragmentation in SQL Server and PostgreSQL.
DO NOT USE Guid.CreateVersion7() or FastGuid.UUID.CreateVersion7() for database Guids.
Use FastGuid.NewSqlServerGuid() or FastGuid.NewPostgreSqlGuid() instead.
public class Bench
{
[Benchmark(Baseline = true)]
public void FastGuid_NewGuid() // 12 calls
{
FastGuid.NewGuid(); FastGuid.NewGuid(); FastGuid.NewGuid(); FastGuid.NewGuid();
FastGuid.NewGuid(); FastGuid.NewGuid(); FastGuid.NewGuid(); FastGuid.NewGuid();
FastGuid.NewGuid(); FastGuid.NewGuid(); FastGuid.NewGuid(); FastGuid.NewGuid();
}
[Benchmark]
public void Guid_NewGuid() // 12 calls
{
Guid.NewGuid(); Guid.NewGuid(); Guid.NewGuid(); Guid.NewGuid();
Guid.NewGuid(); Guid.NewGuid(); Guid.NewGuid(); Guid.NewGuid();
Guid.NewGuid(); Guid.NewGuid(); Guid.NewGuid(); Guid.NewGuid();
}
}//class BenchBenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19045.2364)
Intel Core i7-10510U CPU 1.80GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK=7.0.101
[Host] : .NET 7.0.1 (7.0.122.56804), X64 RyuJIT AVX2| Method | Mean | Error | StdDev | Ratio |
|---|---|---|---|---|
| FastGuid_NewGuid | 116.6 ns | 2.26 ns | 5.19 ns | 1.00 |
| Guid_NewGuid | 1,215.9 ns | 23.85 ns | 45.96 ns | 10.39 |
static long UtcNow() => DateTime.UtcNow.Ticks;
static long StopwatchDT() => Stopwatch.GetTimestamp();
static Guid Fast_Guid() => SecurityDriven.FastGuid.NewGuid();
static Guid Fast_UUID7() => SecurityDriven.FastGuid.UUID.CreateVersion7();
static Guid Fast_MSSqlGuid() => SecurityDriven.FastGuid.NewSqlServerGuid();
static Guid Fast_PGSqlGuid() => SecurityDriven.FastGuid.NewPostgreSqlGuid();
static Guid NewGuid4() => Guid.NewGuid();
static Guid NewGuid7() => Guid.CreateVersion7();BenchmarkDotNet v0.15.1, Windows 11 (10.0.26200.8457)
Intel Core i7-10510U CPU 1.80GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK 11.0.100-preview.4.26230.115
[Host] : .NET 10.0.8 (10.0.826.23019), X64 RyuJIT AVX2| Method | Mean | Error | StdDev | Ratio |
|---|---|---|---|---|
| UtcNow | 25.65 ns | 0.279 ns | 0.233 ns | 2.3x |
| StopwatchDT | 15.26 ns | 0.168 ns | 0.149 ns | 1.4x |
| Fast_Guid | 11.29 ns | 0.259 ns | 0.299 ns | 1.0x |
| Fast_UUID7 | 38.75 ns | 0.719 ns | 0.600 ns | ~ 3x |
| Fast_MSSqlGuid | 37.26 ns | 0.455 ns | 0.380 ns | ~ 3x |
| Fast_PGSqlGuid | 35.31 ns | 0.516 ns | 0.574 ns | ~ 3x |
| NewGuid4 | 93.35 ns | 1.652 ns | 1.545 ns | ~ 8x |
| NewGuid7 | 128.89 ns | 2.132 ns | 1.780 ns | ~11x |
// Generate a 16-character random hexadecimal string
string hex = FastGuid.StringGen.Text16(16); // 64 bits of entropy
// Generate a 32-character random Base32 session identifier
string sessionId = FastGuid.StringGen.Text32(32); // 160 bits of entropy
// Generate a 32-character random Base64Url token
string token = FastGuid.StringGen.Text64Url(32); // 192 bits of entropystatic Guid FastGuid_NewGuid() => FastGuid.NewGuid();
static string FastGuid_StringGen_Text16_16() => FastGuid.StringGen.Text16(16);
static string FastGuid_StringGen_Text32_32() => FastGuid.StringGen.Text32(32);
static string FastGuid_StringGen_Text64Url_32() => FastGuid.StringGen.Text64Url(32);BenchmarkDotNet v0.13.8, Windows 10 (10.0.19045.5917/22H2/2022Update)
Intel Core i7-10510U CPU 1.80GHz, 1 CPU, 8 logical and 4 physical cores
.NET SDK 10.0.100-preview.5.25277.114
[Host] : .NET 10.0.0 (10.0.25.27814), X64 RyuJIT AVX2Guid guid1 = FastGuid.NewGuid();
string guidString = guid1.ToBase64Url(); // e.g. "Q29uZGVuc2VkQmFzZTY0VXJs"
Guid guid2 = guidString.FromBase64Url(); // round-trip; throws if guid string is invalid
if (guid1 != guid2) throw new InvalidOperationException(); // not going to happen
// Exception-free parsing:
if (GuidExtensions.TryFromBase64Url(guidString, out Guid validGuid))
{
// validGuid is valid
}