8 min read

UUID vs GUID: Differences, Compatibility, and Gotchas

Learn how UUIDs and GUIDs relate, understand .NET byte-order differences, and choose a safe interchange format for your application stack.

When designing database schemas, message queues, and cross-platform APIs, software engineers constantly encounter two terms: UUID (Universally Unique Identifier) and GUID (Globally Unique Identifier). Are they different technologies, interchangeable synonyms, or subtly incompatible implementations?

The short answer is: in textual representation, UUID and GUID refer to the exact same 128-bit identifier format. A standard random GUID generated in Microsoft .NET is fully compatible with an RFC 4122 UUID v4 used in Linux, Java, Python, or PostgreSQL. However, beneath the surface lies a critical technical trap: Microsoft's binary storage uses a mixed-endian memory layout, causing raw byte arrays to deserialize into completely different string values when transferred between .NET and non-Microsoft systems.

You can generate and format identifiers using ToolPorta's GUID Generator or UUID Generator. This guide covers their origins, the mixed-endian byte-array gotcha, text conventions, and practical interoperability rules.

Format and text structure#

Both UUID and GUID consist of 128 bits (16 bytes). In string form, they are displayed as 32 hexadecimal digits divided into five hyphen-separated groups according to the canonical 8-4-4-4-12 pattern:

TEXT
1xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx2|      |   |   |   |           |
  • Group 1 (8 hex chars / 32 bits): Low time or pseudo-random data.
  • Group 2 (4 hex chars / 16 bits): Mid time or pseudo-random data.
  • Group 3 (4 hex chars / 16 bits): High time multiplexed with the 4-bit version number M (e.g., 4 for random, 7 for time-ordered).
  • Group 4 (4 hex chars / 16 bits): Variant bit field N (typically 8, 9, a, or b for standard RFC/DCE variant) plus clock sequence or random entropy.
  • Group 5 (12 hex chars / 48 bits): Node MAC address (in v1) or cryptographically secure pseudo-random bytes (in v4).

Typical representation conventions#

While the underlying 128-bit values are identical, the ecosystems surrounding them developed distinct stylistic conventions:

FeatureStandard UUID (RFC 4122 / RFC 9562)Microsoft GUID (Windows / .NET / COM)
Letter CaseUppercase, lowercase, or mixed hexadecimal is validOften uppercase in Microsoft examples
Enclosing BracesNo braces (e04f...)Frequently enclosed in braces ({E04F...})
Nil / Empty StateNil UUID (00000000-0000-0000-0000-000000000000)Guid.Empty (00000000-0000-0000-0000-000000000000)
Primary ContextWeb APIs, Linux, Java, Python, PostgreSQLC#, .NET, Windows Registry, COM, SQL Server

When exchanging data over JSON APIs, choosing one canonical form—commonly lowercase with hyphens and no braces—simplifies comparison and logging. Case alone does not change the 128-bit value.

The critical gotcha: The mixed-endian binary byte swap#

The most dangerous pitfall when bridging .NET and non-Microsoft ecosystems occurs when transferring raw binary representations (16 bytes) rather than string representations.

The Win32 C struct legacy#

In the original Windows C/C++ header files, a GUID was defined not as a flat 16-byte array, but as a composite structure:

C
1typedef struct _GUID {2    unsigned long  Data1;    // 32-bit unsigned integer (4 bytes)3    unsigned short Data2;    // 16-bit unsigned integer (2 bytes)4    unsigned short Data3;    // 16-bit unsigned integer (2 bytes)5    unsigned char  Data4[]; // 8 individual bytes6} GUID;

Because x86 and x64 processors are little-endian, multibyte integer types are stored in memory with their least significant byte first:

  • Data1 (4 bytes) is stored in little-endian byte order.
  • Data2 (2 bytes) is stored in little-endian byte order.
  • Data3 (2 bytes) is stored in little-endian byte order.
  • Data4 is an array of 8 individual bytes, so it is stored sequentially (big-endian).

Conversely, RFC 4122 and RFC 9562 specify that UUIDs must always be stored in big-endian (network byte order), matching their left-to-right hexadecimal string representation.

What happens when you call Guid.ToByteArray()#

Consider the following valid identifier:

TEXT
1String representation: --cdef--

If you serialize this identifier to a 16-byte array in standard RFC 4122 (big-endian) vs default .NET Guid.ToByteArray() on an x86/x64 machine:

TEXT
1RFC  (Standard Big-Endian):2[ , , , ,   , ab,   cd, ef,   , ,   , , , ab, cd, ef ]3|--- Data1 ----|   |-Data2-| |-Data3-|  |----------- Data4 ------------|45.NET Guid.ToByteArray() (Mixed-Endian):6[ , , , ,   ab, ,   ef, cd,   , ,   , , , ab, cd, ef ]7|-- Reversed --|   |-Revd--| |-Revd--|  |--------- Untouched ----------|

Notice the discrepancy:

  1. The first 4 bytes (Data1) are reversed: 01 23 45 67 becomes 67 45 23 01.
  2. The next 2 bytes (Data2) are reversed: 89 ab becomes ab 89.
  3. The next 2 bytes (Data3) are reversed: cd ef becomes ef cd.
  4. The remaining 8 bytes (Data4) remain identical.

If a .NET service saves raw bytes generated by Guid.ToByteArray() into a Kafka message or binary database column, and a Java or Go consumer reads those bytes as a standard RFC 4122 UUID, the consumer produces an entirely different string:

TEXT
1Original .NET GUID:  --cdef--2Java / Go reads it:  -ab89-efcd--

The record cannot be found, foreign key relationships break, and distributed lookups fail silently.

How to fix the endianness mismatch in modern .NET#

Prior to modern .NET, developers had to manually swap bytes before sending binary UUIDs across the wire. Starting in .NET Core and enhanced in .NET 8 / 9, System.Guid includes explicit big-endian support:

C#
1// Exporting to standard RFC 4122 (big-endian) binary:2Guid guid = Guid.NewGuid();3byte[] rfcBytes = new byte[];4guid.TryWriteBytes(rfcBytes, bigEndian: true, out _);56// Parsing from standard RFC 4122 (big-endian) binary:7ReadOnlySpan<byte> incomingNetworkBytes = rfcBytes;8Guid parsedGuid = new Guid(incomingNetworkBytes, bigEndian: true);

When transmitting identifiers across networks or between microservices, serialize identifiers as canonical 36-character hyphenated strings. Strings eliminate endianness ambiguity completely.

Database differences: SQL Server vs PostgreSQL vs MySQL#

Different database management systems handle UUIDs and GUIDs according to their engineering history:

1. Microsoft SQL Server (UNIQUEIDENTIFIER)#

Microsoft SQL Server provides the native UNIQUEIDENTIFIER type, which stores 16 bytes using Microsoft's mixed-endian byte format.

Clustered index fragmentation hazard: SQL Server uses an idiosyncratic collation order for UNIQUEIDENTIFIER. Instead of sorting from byte 0 to 15, SQL Server compares the last 6 bytes of Data4 first, then the first 2 bytes of Data4, followed by Data3, Data2, and Data1.

  • NEWID() generates random GUIDs, so inserts into a clustered GUID index are spread across the keyspace and may increase page splits and cache pressure.
  • To prevent this, SQL Server introduced NEWSEQUENTIALID(), which produces GUIDs that sort consecutively within SQL Server's custom collation order.

2. PostgreSQL (uuid)#

PostgreSQL provides a native uuid type conforming to RFC 4122 / RFC 9562. It stores 16 bytes in big-endian network byte order and sorts them lexicographically.

  • PostgreSQL natively accepts strings with or without hyphens, in uppercase or lowercase, and wrapped in braces {...}.
  • For optimal write performance on large tables, read our comparison on UUID v4 vs UUID v7 to understand why time-ordered v7 keys outperform random keys.

3. MySQL and MariaDB#

MySQL has no dedicated single-purpose UUID type:

  • VARCHAR(36): Simple to read, but occupies 36 bytes per row plus index overhead.
  • BINARY(16): Highly compact (16 bytes). Developers frequently use UUID_TO_BIN(uuid, 1) to swap time fields for sequential indexing when working with legacy UUID v1, or store RFC 9562 UUID v7 directly.

UUID vs GUID comparison matrix#

CriteriaUUID (IETF / RFC)GUID (Microsoft / .NET)
Ratifying BodyIETF (RFC 4122, RFC 9562) & ISO/IECMicrosoft Corporation
Bit Length128 bits (16 bytes)128 bits (16 bytes)
Canonical String Format8-4-4-4-12 hyphenated (36 chars)8-4-4-4-12 hyphenated (36 chars)
Text CasingUppercase, lowercase, or mixed is validUppercase is a historic convention
Curly Braces {}Outside the canonical RFC text form; accepted by some parsersCommon in Windows Registry and COM
Raw Byte LayoutRFC fields use network byte orderLegacy COM and default .NET byte arrays use mixed endianness
Versions Representablev1 through v8 layouts defined by RFC 9562A Guid can hold the same 128 bits; generation APIs depend on platform version
Native Database TypesPostgreSQL uuid, CockroachDB uuidSQL Server uniqueidentifier
Cross-Platform Text ExchangeReliable when peers agree on accepted syntaxReliable in canonical text form
Raw Binary ExchangeDefine network byte order explicitlyConvert default mixed-endian arrays before RFC-order exchange

Step-by-step workflow: Cross-platform identifier handling#

Follow this 4-step checklist to prevent identifier bugs across distributed systems:

  1. Format as text across network boundaries: Always transmit identifiers as 36-character canonical hyphenated strings in REST APIs, GraphQL queries, and JSON documents. Avoid sending raw 16-byte buffers unless using strict binary protocols with defined schemas (like Protocol Buffers).
  2. Normalize casing on ingest: Normalize incoming strings to lowercase before storing them in case-sensitive key-value stores (such as Redis or DynamoDB string keys) to avoid duplicate cache lookups.
  3. Strip braces before URI generation: If generating URLs, route parameters, or file paths from .NET GUIDs, strip surrounding curly braces {} and quotes using ToolPorta's GUID Generator formatting controls.
  4. Specify endianness explicitly in binary protocols: If you must transmit binary 16-byte payloads from C# or .NET, use guid.TryWriteBytes(span, bigEndian: true) rather than guid.ToByteArray().

Frequently asked questions#

Are UUID and GUID interchangeable?#

Their canonical hyphenated text usually represents the same 128-bit value. Interchange is reliable when both sides accept the same syntax and UUID variant. Braced forms, unusual variants, parser policies, and raw byte arrays still require an explicit contract.

Why does .NET reverse the first three groups of bytes?#

In the early 1990s, Microsoft defined GUID as a C structure containing three integer fields (unsigned long, unsigned short, unsigned short) and one byte array (unsigned char[8]). Because x86 architecture is little-endian, those integer fields are stored in memory with their least significant bytes first. When .NET serialized the struct directly to memory via ToByteArray(), it preserved this mixed-endian layout.

Should I store GUIDs as uppercase or lowercase in my database?#

If you use text columns, normalize to one case before comparison; lowercase is a common convention, not an RFC requirement. Prefer native UUID/GUID or 16-byte binary types where appropriate, and avoid multiple textual spellings of the same value in case-sensitive stores.

Can I insert a Microsoft GUID into a PostgreSQL uuid column?#

Yes. PostgreSQL's uuid parser is flexible. It accepts GUIDs formatted with uppercase letters, lowercase letters, or enclosed in curly braces ({...}). PostgreSQL parses the text and stores the resulting 128-bit value in canonical big-endian format.

Does GUID support modern time-ordered UUID v7?#

Yes. .NET 9 added Guid.CreateVersion7(). Its 48-bit millisecond timestamp improves index locality compared with random GUIDs, but no identifier format can promise zero fragmentation; database behavior still depends on the index and workload.

Ensure seamless identifier formatting and testing across your development workflow with ToolPorta's browser utilities:

  • Use the GUID Generator to produce bulk GUIDs with custom braces, casing, hyphens, and prefixes tailored for .NET and Windows projects.
  • Use the UUID Generator to generate RFC 9562 UUID v7 and UUID v4 identifiers for modern databases and web microservices.
  • Explore the NanoID Generator for collision-resistant, URL-safe, compact string IDs.
  • Read our C# GUID developer guide and equivalent JavaScript UUID examples for implementation guidance.
  • Review our architectural guide on UUID v4 vs UUID v7 to optimize relational database primary key indexing.