SQLite is the most widely deployed database in the world — embedded in every iOS and Android device, every Python installation, and countless desktop and server applications. It has no native UUID column type, but UUIDs work well once you choose the right storage format.

Storage Options

SQLite’s type affinity system accepts any value in any column. Two practical choices for UUID storage:

FormatSizeSort orderShell readability
TEXT (36-char hyphenated)36 bytesLexicographic ✓ for v7✓ Human-readable
BLOB (16 raw bytes)16 bytesByte-order ✓ for v7✗ Binary

For UUID v7, both formats preserve sort order correctly: the hyphenated TEXT string sorts lexicographically in the same order as the raw bytes. For UUID v4 (fully random), neither format gives ordered inserts — order is random regardless of column type.

UUID v7 in Python with sqlite3

Python 3.13’s uuid.uuid7() combined with the standard sqlite3 module:

import sqlite3
import uuid

conn = sqlite3.connect("app.db")
conn.execute("""
    CREATE TABLE IF NOT EXISTS orders (
        id TEXT PRIMARY KEY,
        customer_id TEXT NOT NULL,
        status TEXT NOT NULL
    )
""")

# Insert with UUID v7 primary key
order_id = str(uuid.uuid7())
conn.execute(
    "INSERT INTO orders (id, customer_id, status) VALUES (?, ?, ?)",
    (order_id, str(uuid.uuid7()), "pending"),
)
conn.commit()

For BLOB storage, pass uuid.uuid7().bytes instead of str(uuid.uuid7()).

UUID v7 in Go with modernc.org/sqlite

The pure-Go modernc.org/sqlite driver (no CGo required):

import (
    "database/sql"
    "github.com/google/uuid"
    _ "modernc.org/sqlite"
)

db, _ := sql.Open("sqlite", "app.db")

id := uuid.Now_v7() // time-ordered v7
db.Exec(
    "INSERT INTO orders (id, status) VALUES (?, ?)",
    id.String(), "pending",
)

UUID v7 in Node.js with better-sqlite3

better-sqlite3 is the most common synchronous SQLite library for Node.js:

import Database from 'better-sqlite3';
import { v7 as uuidv7 } from 'uuid';

const db = new Database('app.db');
const insert = db.prepare('INSERT INTO orders (id, status) VALUES (?, ?)');
insert.run(uuidv7(), 'pending');

ROWID Tables and UUID Primary Keys

By default, SQLite creates a ROWID table — every row gets an implicit 64-bit integer rowid used as the actual B-tree key. Declaring a TEXT PRIMARY KEY creates a separate index on the UUID column, meaning the UUID index and the ROWID index coexist. To use the UUID as the true B-tree key (eliminating the duplicate index), declare it as WITHOUT ROWID:

CREATE TABLE orders (
    id TEXT PRIMARY KEY,
    status TEXT NOT NULL
) WITHOUT ROWID;

With WITHOUT ROWID and UUID v7 values, inserts append to the right side of the B-tree exactly as they would with an autoincrement integer. This is the most storage-efficient setup for UUID v7 primary keys in SQLite.

Frequently asked questions

How do I store UUIDs in SQLite?

SQLite has no native UUID type. Use TEXT (36-char string, human-readable) or BLOB (16-byte binary, more efficient). For UUID v7, BLOB with WITHOUT ROWID gives the best index performance since v7's sequential bytes reduce page splits. Generate UUID v7 in the application layer using the uuid npm package, Python's uuid.uuid7() (3.13+), or the google/uuid Go package.

What column type should I use to store a UUID in a database?

Use the native type where one exists — uuid in PostgreSQL, uniqueidentifier in SQL Server. In MySQL use BINARY(16) and store raw bytes. Avoid VARCHAR(36): it costs 36 bytes per row versus 16 for binary and makes every comparison a string operation.

Should I use v4 or v7?

Use v7 for database primary keys (time-sortable, index-friendly) and v4 for anything where creation order could leak information, like tokens or share links.

What column type should I use for UUIDs in SQLite?

Use BLOB (16 bytes) for best performance, or TEXT (36 chars) for readability. SQLite's dynamic typing will accept either without a schema change. BLOB is half the size and faster to compare in indexes; TEXT is easier to read in sqlite3 shell and debug tools. For UUID v7, BLOB preserves the byte-level sort order that makes the primary key index sequential.

Does UUID v7 improve SQLite insert performance?

Yes. SQLite uses a B-tree for its primary key index just like PostgreSQL and MySQL. UUID v4 scatters inserts randomly across the tree, causing page splits. UUID v7's monotonically increasing value keeps new rows near the last page — similar to SQLite's built-in ROWID / AUTOINCREMENT behaviour but globally unique.