TidesDB Lua API Reference
If you want to download the source of this document, you can find it here.
Getting Started
Prerequisites
You must have the TidesDB shared C library installed on your system. You can find the installation instructions here.
You also need LuaJIT 2.1+ or Lua 5.1+ with LuaFFI installed.
Installation
Using LuaRocks
luarocks install tidesdbManual Installation
# Clone the repositorygit clone https://github.com/tidesdb/tidesdb-lua.git
# Copy to your Lua package pathcp tidesdb-lua/src/tidesdb.lua /usr/local/share/lua/5.1/Custom Installation Paths
If you installed TidesDB to a non-standard location, you can specify custom paths using environment variables:
# Set custom library pathexport LD_LIBRARY_PATH="/custom/path/lib:$LD_LIBRARY_PATH" # Linux# orexport DYLD_LIBRARY_PATH="/custom/path/lib:$DYLD_LIBRARY_PATH" # macOSCustom prefix installation
# Install TidesDB to custom locationcd tidesdbcmake -S . -B build -DCMAKE_INSTALL_PREFIX=/opt/tidesdbcmake --build buildsudo cmake --install build
# Configure library pathexport LD_LIBRARY_PATH="/opt/tidesdb/lib:$LD_LIBRARY_PATH" # Linux# orexport DYLD_LIBRARY_PATH="/opt/tidesdb/lib:$DYLD_LIBRARY_PATH" # macOSUsage
Opening and Closing a Database
local tidesdb = require("tidesdb")
local db = tidesdb.TidesDB.open("./mydb", { num_flush_threads = 2, num_compaction_threads = 2, log_level = tidesdb.LogLevel.LOG_INFO, block_cache_size = 64 * 1024 * 1024, max_open_sstables = 256,})
print("Database opened successfully")
db:close()Creating and Dropping Column Families
Column families are isolated key-value stores with independent configuration.
local cf_config = tidesdb.default_column_family_config()db:create_column_family("my_cf", cf_config)
-- Create with custom configuration based on defaultslocal cf_config = tidesdb.default_column_family_config()
-- You can modify the configuration as neededcf_config.write_buffer_size = 128 * 1024 * 1024cf_config.level_size_ratio = 10cf_config.min_levels = 5cf_config.compression_algorithm = tidesdb.CompressionAlgorithm.LZ4_COMPRESSIONcf_config.enable_bloom_filter = truecf_config.bloom_fpr = 0.01cf_config.enable_block_indexes = truecf_config.sync_mode = tidesdb.SyncMode.SYNC_INTERVALcf_config.sync_interval_us = 128000cf_config.default_isolation_level = tidesdb.IsolationLevel.READ_COMMITTED
db:create_column_family("my_cf", cf_config)
db:drop_column_family("my_cf")CRUD Operations
All operations in TidesDB are performed through transactions for ACID guarantees.
Writing Data
local cf = db:get_column_family("my_cf")
local txn = db:begin_txn()
-- Put a key-value pair (TTL -1 means no expiration)txn:put(cf, "key", "value", -1)
txn:commit()txn:free()Writing with TTL
local cf = db:get_column_family("my_cf")
local txn = db:begin_txn()
-- Set expiration time (Unix timestamp)local ttl = os.time() + 10 -- Expire in 10 seconds
txn:put(cf, "temp_key", "temp_value", ttl)
txn:commit()txn:free()TTL Examples
-- No expirationlocal ttl = -1
-- Expire in 5 minuteslocal ttl = os.time() + 5 * 60
-- Expire in 1 hourlocal ttl = os.time() + 60 * 60
-- Expire at specific timelocal ttl = os.time({year=2026, month=12, day=31, hour=23, min=59, sec=59})Reading Data
local cf = db:get_column_family("my_cf")
local txn = db:begin_txn()
local value = txn:get(cf, "key")
print("Value: " .. value)
txn:free()Deleting Data
local cf = db:get_column_family("my_cf")
local txn = db:begin_txn()
txn:delete(cf, "key")
txn:commit()txn:free()Multi-Operation Transactions
local cf = db:get_column_family("my_cf")
local txn = db:begin_txn()
-- Multiple operations in one transaction, across column families as welllocal ok, err = pcall(function() txn:put(cf, "key1", "value1", -1) txn:put(cf, "key2", "value2", -1) txn:delete(cf, "old_key")end)
if not ok then txn:rollback() error(err)end
-- Commit atomically -- all or nothingtxn:commit()txn:free()Iterating Over Data
Iterators provide efficient bidirectional traversal over key-value pairs.
Forward Iteration
local cf = db:get_column_family("my_cf")
local txn = db:begin_txn()
local iter = txn:new_iterator(cf)
iter:seek_to_first()
while iter:valid() do local key = iter:key() local value = iter:value()
print(string.format("Key: %s, Value: %s", key, value))
iter:next()end
iter:free()txn:free()Backward Iteration
local cf = db:get_column_family("my_cf")
local txn = db:begin_txn()
local iter = txn:new_iterator(cf)
iter:seek_to_last()
while iter:valid() do local key = iter:key() local value = iter:value()
print(string.format("Key: %s, Value: %s", key, value))
iter:prev()end
iter:free()txn:free()Getting Column Family Statistics
Retrieve detailed statistics about a column family.
local cf = db:get_column_family("my_cf")
local stats = cf:get_stats()
print(string.format("Number of Levels: %d", stats.num_levels))print(string.format("Memtable Size: %d bytes", stats.memtable_size))
if stats.config then print(string.format("Write Buffer Size: %d", stats.config.write_buffer_size)) print(string.format("Compression: %d", stats.config.compression_algorithm)) print(string.format("Bloom Filter: %s", tostring(stats.config.enable_bloom_filter))) print(string.format("Sync Mode: %d", stats.config.sync_mode))endListing Column Families
local cf_list = db:list_column_families()
print("Available column families:")for _, name in ipairs(cf_list) do print(" - " .. name)endCompaction
Manual Compaction
local cf = db:get_column_family("my_cf")
-- Manually trigger compaction (queues compaction from L1+)local ok, err = pcall(function() cf:compact()end)if not ok then print("Compaction note: " .. tostring(err))endManual Memtable Flush
local cf = db:get_column_family("my_cf")
-- Manually trigger memtable flush (queues memtable for sorted run to disk (L1))local ok, err = pcall(function() cf:flush_memtable()end)if not ok then print("Flush note: " .. tostring(err))endSync Modes
Control the durability vs performance tradeoff.
local cf_config = tidesdb.default_column_family_config()
-- SYNC_NONE -- Fastest, least durable (OS handles flushing on sorted runs and compaction to sync after completion)cf_config.sync_mode = tidesdb.SyncMode.SYNC_NONE
-- SYNC_INTERVAL -- Balanced (periodic background syncing)cf_config.sync_mode = tidesdb.SyncMode.SYNC_INTERVALcf_config.sync_interval_us = 128000 -- Sync every 128ms
-- SYNC_FULL -- Most durable (fsync on every write)cf_config.sync_mode = tidesdb.SyncMode.SYNC_FULL
db:create_column_family("my_cf", cf_config)Compression Algorithms
TidesDB supports multiple compression algorithms:
local cf_config = tidesdb.default_column_family_config()
cf_config.compression_algorithm = tidesdb.CompressionAlgorithm.NO_COMPRESSIONcf_config.compression_algorithm = tidesdb.CompressionAlgorithm.LZ4_COMPRESSIONcf_config.compression_algorithm = tidesdb.CompressionAlgorithm.LZ4_FAST_COMPRESSIONcf_config.compression_algorithm = tidesdb.CompressionAlgorithm.ZSTD_COMPRESSION
db:create_column_family("my_cf", cf_config)Error Handling
local cf = db:get_column_family("my_cf")
local txn = db:begin_txn()
local ok, err = pcall(function() txn:put(cf, "key", "value", -1)end)
if not ok then -- Errors include context and error codes print("Error: " .. tostring(err))
-- Example error message: -- "TidesDBError: failed to put key-value pair: memory allocation failed (code: -1)"
txn:rollback() returnend
txn:commit()txn:free()Error Codes
TDB_SUCCESS(0) — Operation successfulTDB_ERR_MEMORY(-1) — Memory allocation failedTDB_ERR_INVALID_ARGS(-2) — Invalid argumentsTDB_ERR_NOT_FOUND(-3) — Key not foundTDB_ERR_IO(-4) — I/O errorTDB_ERR_CORRUPTION(-5) — Data corruptionTDB_ERR_EXISTS(-6) — Resource already existsTDB_ERR_CONFLICT(-7) — Transaction conflictTDB_ERR_TOO_LARGE(-8) — Key or value too largeTDB_ERR_MEMORY_LIMIT(-9) — Memory limit exceededTDB_ERR_INVALID_DB(-10) — Invalid database handleTDB_ERR_UNKNOWN(-11) — Unknown errorTDB_ERR_LOCKED(-12) — Database is locked
Complete Example
local tidesdb = require("tidesdb")
local db = tidesdb.TidesDB.open("./example_db", { num_flush_threads = 1, num_compaction_threads = 1, log_level = tidesdb.LogLevel.LOG_INFO, block_cache_size = 64 * 1024 * 1024, max_open_sstables = 256,})
local cf_config = tidesdb.default_column_family_config()cf_config.write_buffer_size = 64 * 1024 * 1024cf_config.compression_algorithm = tidesdb.CompressionAlgorithm.LZ4_COMPRESSIONcf_config.enable_bloom_filter = truecf_config.bloom_fpr = 0.01cf_config.sync_mode = tidesdb.SyncMode.SYNC_INTERVALcf_config.sync_interval_us = 128000
db:create_column_family("users", cf_config)
local cf = db:get_column_family("users")
local txn = db:begin_txn()
txn:put(cf, "user:1", "Alice", -1)txn:put(cf, "user:2", "Bob", -1)
local ttl = os.time() + 30 -- Expire in 30 secondstxn:put(cf, "session:abc", "temp_data", ttl)
txn:commit()txn:free()
local read_txn = db:begin_txn()
local value = read_txn:get(cf, "user:1")print("user:1 = " .. value)
local iter = read_txn:new_iterator(cf)
print("\nAll entries:")iter:seek_to_first()while iter:valid() do local key = iter:key() local val = iter:value() print(string.format(" %s = %s", key, val)) iter:next()enditer:free()
read_txn:free()
local stats = cf:get_stats()
print("\nColumn Family Statistics:")print(string.format(" Number of Levels: %d", stats.num_levels))print(string.format(" Memtable Size: %d bytes", stats.memtable_size))
db:drop_column_family("users")db:close()Isolation Levels
TidesDB supports five MVCC isolation levels:
local txn = db:begin_txn_with_isolation(tidesdb.IsolationLevel.READ_COMMITTED)
txn:free()Available Isolation Levels
READ_UNCOMMITTED— Sees all data including uncommitted changesREAD_COMMITTED— Sees only committed data (default)REPEATABLE_READ— Consistent snapshot, phantom reads possibleSNAPSHOT— Write-write conflict detectionSERIALIZABLE— Full read-write conflict detection (SSI)
Savepoints
Savepoints allow partial rollback within a transaction:
local txn = db:begin_txn()
txn:put(cf, "key1", "value1", -1)
txn:savepoint("sp1")txn:put(cf, "key2", "value2", -1)
-- Rollback to savepoint -- key2 is discarded, key1 remainstxn:rollback_to_savepoint("sp1")
-- Commit -- only key1 is writtentxn:commit()txn:free()Testing
# Run all tests with LuaJITcd testsluajit test_tidesdb.lua
# Run with standard Lua (requires LuaFFI)lua test_tidesdb.lua