uuid
uuid
Level 2 — Data Types & Record Structure The primitive data type in SurrealDB that stores 128-bit Universally Unique Identifiers (UUIDs) natively, providing efficient storage and indexing of unique hashes.
1. Prerequisites
- Data Types (Overview) — The parent type system.
2. Term Category
Data Type (universally unique identifier type): - Database Structure / Paradigm
3. Explanation
(1) Design Motivation — "Why did we design this?"
In modern web applications, you need unique identifiers that cannot be guessed:
- If you use sequential IDs (like order
1,2,3), an attacker can guess IDs and download other users' invoices. - If you run a distributed database, sequential IDs trigger sync collisions because two nodes might write order
4simultaneously.
To solve this, developers use UUIDs (Universally Unique Identifiers): 128-bit numbers that are globally unique.
In PostgreSQL, UUIDs are supported natively.
In MongoDB, they are often saved as binary strings (BinData), which are difficult to read in shell consoles.
We designed the native uuid data type in SurrealDB to provide first-class support.
It stores UUID values as efficient 16-byte binary blocks on disk, keeping index sizes small.
At the same time, it prints them in standard readable text formats in queries and provides built-in generation functions (like rand::uuid()), simplifying ID management.
(2) Built-In Generation
SurrealDB provides standard functions to handle UUIDs:
rand::uuid(): Generates a new cryptographically random UUID (Version 4).- Explicit Casting: You can convert a valid UUID string into a native
uuidtype using the<uuid>casting operator:<uuid> "b1a457f9-8c2d-4f10-b67c-5a1248cf9af4".
(3) Reality Metaphor (Global Barcode Stickers)
Imagine tagging shipping containers:
- Sequential IDs: Writing numbers
1,2,3with a marker. It is easy, but if another warehouse uses the same numbers, the tracking system breaks during mergers. uuidType: Stamping every container with a Global Barcode Sticker.- The barcode has a complex, 128-bit pattern of lines.
- No other container in any port worldwide will ever have the exact same barcode.
- It doesn't represent date or location; it simply guarantees the item is unique.
(4) Code Examples
Creating and Using UUID Fields
Let's model a device token registration schema:
DEFINE TABLE device SCHEMAFULL;
-- 1. Enforce UUID type
DEFINE FIELD device_id ON device TYPE uuid;
DEFINE FIELD token ON device TYPE string;
-- 2. Insert records using built-in generator functions
CREATE device SET
device_id = rand::uuid(), // Generates a random v4 UUID
token = "some_apns_token";
-- 3. Query using a UUID literal (SurrealDB parses it as uuid type!)
SELECT * FROM device WHERE device_id = <uuid> "b1a457f9-8c2d-4f10-b67c-5a1248cf9af4";
4. Common Mistakes & Pitfalls
Mistake 1: Storing UUID values as standard text strings, wasting index storage and CPU RAM cache space
The mistake: Defining a UUID tracking field as TYPE string and saving the 36-character string representation into it.
Why it's wrong: Storing a UUID as a string takes 36 bytes of storage space (one byte per character).
Declaring it as TYPE uuid tells the database to store it as a compressed 16-byte binary block.
Under millions of records, using strings increases your index storage footprint by over 100%, causing index scans to consume more server memory.
Fix: Always define unique hash fields as TYPE uuid to trigger binary storage compression.
Mistake 2: Storing UUIDs as Plain Text Strings instead of Native UUID Primitives
The mistake: Storing "f47ac10b-58cc-4372-a567-0e02b2c3d479" in fields defined as TYPE string.
Why it's wrong: Plain strings occupy 36 bytes of text storage. Native TYPE uuid stores UUIDs in binary 16-byte format, saving storage and indexing space.
Incorrect:
DEFINE FIELD id_code ON TABLE log TYPE string; // ❌ 36 bytes text overhead
Fix:
DEFINE FIELD id_code ON TABLE log TYPE uuid; // Efficient 16-byte binary UUID
Mistake 3: Passing Invalid UUID Formatting Strings to <uuid> Casts
The mistake: Casting <uuid> "invalid-uuid-string".
Why it's wrong: SurrealDB validates 8-4-4-4-12 hex formatting. Passing invalid strings throws a casting error.
Incorrect:
RETURN <uuid> "12345"; // ❌ Invalid UUID string format
Fix:
RETURN <uuid> "f47ac10b-58cc-4372-a567-0e02b2c3d479"; // Valid 36-char UUID string
5. Practice Exercises
Exercise 1: UUID Field Definition and Generation
Scenario: A microservice architecture requires globally unique UUID identifiers for distributed order tracking.
Requirements:
- Define table
ordersinSCHEMAFULLmode. - Define field
tracking_idasuuiddefaulting torand::uuid(). - Create an order record
orders:o1.
Answer
Implementation
DEFINE TABLE orders SCHEMAFULL;
DEFINE FIELD tracking_id ON TABLE orders TYPE uuid DEFAULT rand::uuid();
CREATE orders:o1 SET amount = 250.00dec;
SELECT * FROM orders:o1;
Technical Explanation
TYPE uuidrestricts field values strictly to valid 128-bit UUID bytes/strings.rand::uuid()generates cryptographically random UUID v4 values automatically.- Guarantees global identifier uniqueness across distributed database clusters.
Exercise 2: UUID Record Primary Key Creation
Scenario:
Create a record in table session where the primary key itself is a generated UUID (session:uuid()).
Requirements:
- Write the
CREATEstatement usingsession:uuid(). - Inspect the returned primary key.
Answer
Implementation
CREATE session:uuid() SET user = user:alice, logged_in = time::now();
Technical Explanation
session:uuid()uses SurrealDB's built-in UUID primary key generator function.- Generates record IDs in the format
session:u'018c4e6a-7b3f-7123-89ab-cdef01234567'. - Provides unique, unguessable primary keys for sensitive authentication sessions.
Exercise 3: Parsing and Validating UUID Strings
Scenario:
Verify whether a given string is a valid UUID before storing it in a uuid field using is::uuid().
Requirements:
- Test validity of string
"018c4e6a-7b3f-7123-89ab-cdef01234567"usingstring::is::uuid().
Answer
Implementation
SELECT string::is::uuid("018c4e6a-7b3f-7123-89ab-cdef01234567") AS valid_uuid;
-- Output: { valid_uuid: true }
Technical Explanation
string::is::uuid(str)validates whether a string matches standard 36-character UUID formatting.- Used inside field
ASSERTclauses to sanitize incoming string parameters. - Prevents invalid UUID strings from reaching application logic.
6. Related Terms
- Data Types (Overview) — The parent type system.
- ID Generation Strategies (
ulid(),uuid(),rand::*, String, Numeric) — Generating Record IDs.
7. Key Takeaways
- The
uuidtype stores 128-bit Universally Unique Identifiers natively. - Direct NoSQL equivalent to PostgreSQL's native
UUIDcolumn type. - Stored as a compressed 16-byte binary block on disk, saving index space.
- Displayed as a standard 36-character readable string in query results.
- Generate random UUIDs using the built-in function
rand::uuid(). - Convert string inputs to UUIDs using the
<uuid>explicit casting operator. - Avoid storing UUID hashes in
stringfields to prevent index bloat.