Skip to content

Schema

Redlite stores data in SQLite using a multi-table schema designed for Redis compatibility while leveraging SQLite’s strengths.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ keys β”‚
β”‚ (db, key) β†’ type, expires_at, created_at, updated_at β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚
β–Ό β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ strings β”‚ β”‚ hashes β”‚ β”‚ lists β”‚
β”‚ (db, key) β”‚ β”‚ (db, key, β”‚ β”‚ (db, key, β”‚
β”‚ β†’ value β”‚ β”‚ field) β”‚ β”‚ position) β”‚
β”‚ β”‚ β”‚ β†’ value β”‚ β”‚ β†’ value β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ sets β”‚ β”‚ zsets β”‚
β”‚ (db, key, β”‚ β”‚ (db, key, β”‚
β”‚ member) β”‚ β”‚ member) β”‚
β”‚ β”‚ β”‚ β†’ score β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Central metadata table for all keys.

CREATE TABLE keys (
db INTEGER NOT NULL DEFAULT 0,
key TEXT NOT NULL,
type TEXT NOT NULL CHECK (type IN ('string', 'hash', 'list', 'set', 'zset')),
expires_at INTEGER, -- Unix timestamp (milliseconds)
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
PRIMARY KEY (db, key)
);
ColumnTypeDescription
dbINTEGERDatabase number (0-15)
keyTEXTKey name
typeTEXTData type (string, hash, list, set, zset)
expires_atINTEGERExpiration timestamp in milliseconds (NULL = no expiry)
created_atINTEGERCreation timestamp in milliseconds
updated_atINTEGERLast update timestamp in milliseconds

String values (binary data stored as BLOB).

CREATE TABLE strings (
db INTEGER NOT NULL DEFAULT 0,
key TEXT NOT NULL,
value BLOB NOT NULL,
PRIMARY KEY (db, key),
FOREIGN KEY (db, key) REFERENCES keys(db, key) ON DELETE CASCADE
);

Hash field-value pairs.

CREATE TABLE hashes (
db INTEGER NOT NULL DEFAULT 0,
key TEXT NOT NULL,
field TEXT NOT NULL,
value BLOB NOT NULL,
PRIMARY KEY (db, key, field),
FOREIGN KEY (db, key) REFERENCES keys(db, key) ON DELETE CASCADE
);

List elements with gap-based positioning for O(1) push operations.

CREATE TABLE lists (
db INTEGER NOT NULL DEFAULT 0,
key TEXT NOT NULL,
position REAL NOT NULL, -- Gap-based for efficient insert
value BLOB NOT NULL,
PRIMARY KEY (db, key, position),
FOREIGN KEY (db, key) REFERENCES keys(db, key) ON DELETE CASCADE
);

The position column uses REAL (floating point) to allow efficient insertions:

  • Initial elements: 1.0, 2.0, 3.0, …
  • Insert between 1.0 and 2.0: 1.5
  • Insert between 1.0 and 1.5: 1.25

Set members (unique values per key).

CREATE TABLE sets (
db INTEGER NOT NULL DEFAULT 0,
key TEXT NOT NULL,
member BLOB NOT NULL,
PRIMARY KEY (db, key, member),
FOREIGN KEY (db, key) REFERENCES keys(db, key) ON DELETE CASCADE
);

Sorted set members with scores.

CREATE TABLE zsets (
db INTEGER NOT NULL DEFAULT 0,
key TEXT NOT NULL,
member BLOB NOT NULL,
score REAL NOT NULL,
PRIMARY KEY (db, key, member),
FOREIGN KEY (db, key) REFERENCES keys(db, key) ON DELETE CASCADE
);
CREATE INDEX zsets_score ON zsets(db, key, score);
-- Fast expiration lookups
CREATE INDEX keys_expires ON keys(expires_at) WHERE expires_at IS NOT NULL;
-- Fast score-based queries for sorted sets
CREATE INDEX zsets_score ON zsets(db, key, score);

All value tables reference the keys table with ON DELETE CASCADE. When a key is deleted from keys, the corresponding data is automatically removed.

-- Deleting from keys table
DELETE FROM keys WHERE db = 0 AND key = 'mykey';
-- Automatically removes related rows from strings, hashes, lists, sets, or zsets

The type column in keys ensures a key can only have one type at a time. Attempting to use a key with a different type results in a WRONGTYPE error (matching Redis behavior).

Expiration is stored as Unix timestamp in milliseconds in expires_at. Keys are lazily expired:

  1. On read: Check expires_at, delete if expired
  2. Background cleanup: Not yet implemented (planned)

Redlite enables SQLite’s Write-Ahead Logging (WAL) mode:

  • Concurrent reads while writing
  • Better performance for mixed read/write workloads
  • Crash recovery