.NET Guid byte order: why ToByteArray() and SQL Server sort your GUIDs wrong
Short answer
Guid.ToByteArray() in .NET is mixed-endian: it reverses the first three groups of the GUID (4, 2 and 2 bytes) and leaves the last 8 bytes as written. SQL Server's uniqueidentifier sorts in yet another order, with the last six bytes most significant. So a time-ordered UUIDv7 stops being time-ordered the moment you store it either way. The fix on .NET 8+: ToByteArray(bigEndian: true) into a binary(16) column.

Part of the article Pick a UUIDv7 library that keeps order: 10 tested, .NET fails 50%. This page answers one question from it in depth.
On this page · 8 sections
This is a 1990s Windows layout decision still taxing every .NET shop that adopts UUIDv7 in 2026. Nobody announces it; your index just fragments and your "sort by id" quietly lies. We found it while testing UUIDv7 libraries across languages, and counted the damage.
Key facts
| What | Fact | Source (checked Oct 26 2026) |
|---|---|---|
ToByteArray() layout |
first 4-byte and next two 2-byte groups reversed, last 8 bytes as in the string | Microsoft Learn: Guid.ToByteArray |
| Big-endian overload | ToByteArray(bool bigEndian), .NET 8 and later |
Microsoft Learn: Guid.ToByteArray |
| UUIDv7 in .NET | Guid.CreateVersion7(), .NET 9 and later, RFC 9562 |
Microsoft Learn: Guid.CreateVersion7 |
| SQL Server sort | last six bytes most significant | Microsoft Learn: Comparing GUID and uniqueidentifier values |
| UUIDv7 timestamp position | first 48 bits (bytes 0 to 5) | RFC 9562, section 5.7 |
Our count, ToByteArray() bytes in binary(16) |
234 backward steps per minute at 1 ID per ms | Our UUIDv7 library test |
The three byte orders
Take one GUID, 018f3a2b-7c4d-7e5f-8a9b-0c1d2e3f4a5b:
- String / RFC order:
01 8F 3A 2B 7C 4D 7E 5F 8A 9B 0C 1D 2E 3F 4A 5B ToByteArray():2B 3A 8F 01 4D 7C 5F 7E 8A 9B 0C 1D 2E 3F 4A 5B- SQL Server compare order: starts at
0C 1D 2E 3F 4A 5B, the last six bytes, then works back through the groups.
The .NET layout mirrors the old Windows GUID struct: a 32-bit field, two 16-bit fields, then 8 raw bytes, with the integers stored little-endian on x86. Microsoft's own example shows 35918bc9-... coming out as C9 8B 91 35 ....
Where each system starts comparing. Card by Tensorust from Microsoft's docs and RFC 9562.
Why UUIDv7 breaks
UUIDv7 exists to be sortable: the millisecond timestamp sits in the first six bytes, big-endian, so newer IDs compare larger (see UUIDv7 vs UUIDv4). Two things undo that in .NET:
ToByteArray()intobinary(16). The flip puts the low bytes of the timestamp's first group ahead of its high bytes, so stored order jumps backward every 256 ms when the low byte rolls over. Our run, oneCreateVersion7()per millisecond: 234 backward steps per minute. WithToByteArray(bigEndian: true): zero.uniqueidentifiercolumns. SQL Server compares the last six bytes first. In a v7 GUID those are random, so inserts land all over the index: the exact page-split problem UUIDv7 was meant to fix.
From our UUIDv7 library test. One ID per millisecond for one minute.
The fix
- Bytes: on .NET 8+, always write
guid.ToByteArray(bigEndian: true)and read back withnew Guid(bytes, bigEndian: true). Store inbinary(16)and the sort matches time. - SQL Server keys: if the column must stay
uniqueidentifier, do not rely on v7 for insert order. Use an ID whose last bytes increase (SQL Server'sNEWSEQUENTIALID()works that way) or cluster on adatetime2or bigint column. - Order inside one millisecond:
CreateVersion7()fills the rest with random bits, so IDs from the same millisecond are not ordered among themselves; our library test measured that too. To pull the timestamp back out and check, see how to extract the timestamp from a UUIDv7.
Common misconceptions
"A GUID is just 16 bytes, order does not matter."
The recordIt matters the moment you sort or index the bytes. The string, .NET's array and SQL Server disagree on which byte comes first.
"CreateVersion7() makes SQL Server keys sequential."
The recordNot in a uniqueidentifier column. SQL Server reads the random tail first.
"ToByteArray() follows the CPU's endianness."
The recordThe documented layout is fixed; use the bigEndian overload when you want RFC order.
Related
- UUIDv7 libraries tested
- UUIDv7 vs UUIDv4
- Extract the timestamp from a UUIDv7
- UUID primary keys in Postgres
FAQ
What byte order does Guid.ToByteArray() use?
Mixed-endian. Per Microsoft's docs, the first four-byte group and the next two two-byte groups are reversed (little-endian), while the last two-byte group and the six-byte group stay in the order of the string.
How do I get a GUID's bytes in big-endian order in .NET?
On .NET 8 or later call guid.ToByteArray(bigEndian: true). It writes the 16 bytes in the same order as the string form, which is the RFC 9562 order.
How does SQL Server sort uniqueidentifier?
Not by the string. Microsoft documents that SqlGuid and SQL Server treat the last six bytes as most significant. The commonly observed full order is bytes 10 to 15, then 8 to 9, 6 to 7, 4 to 5 and 0 to 3.
Is Guid.CreateVersion7() sortable in SQL Server?
Not as a uniqueidentifier key. UUIDv7 puts the timestamp in the first six bytes, and SQL Server compares the last six bytes first, which are random. Store it as binary(16) written with ToByteArray(bigEndian: true), or keep a separate time column for ordering.
Which .NET version added CreateVersion7?
.NET 9 added Guid.CreateVersion7(), following RFC 9562.
Sources
All checked October 26, 2026.
- Microsoft Learn, Guid.ToByteArray: byte order remarks; ToByteArray(bool bigEndian) on .NET 8+.
- Microsoft Learn, Guid.CreateVersion7: .NET 9+, RFC 9562 version 7, random rand_a and rand_b.
- Microsoft Learn, Comparing GUID and uniqueidentifier values: SqlGuid uses SQL Server behavior, last six bytes most significant.
- IETF, RFC 9562 section 5.7: UUIDv7 layout, 48-bit Unix millisecond timestamp first.
- Tensorust, UUIDv7 libraries tested: our .NET run, 234 backward steps per minute.
- Images: cards by Tensorust.
Next question
Every number on this page links to its source and was checked on Oct 26, 2026. Spot an error or a newer figure? Email matt@tensorust.com and it gets fixed.
Read next
- Article · Oct 23, 2026Pick a UUIDv7 library that keeps order: 10 tested, .NET fails 50%
- Guide · Oct 26, 2026How to fix "MAC verification failed during PKCS12 import" (the legacy .p12 fix)
- Explainer · Oct 26, 2026How much does a GitHub Actions macOS runner cost?
Get the next one by email.
What my AI agents tried this week, with the real numbers: what worked, what flopped, what made money. One email when there is something worth reading.
No spam, never sold. Every email has a one-click unsubscribe.
