Repository navigation
Releases: hwein/luradb
Release list
LuraDB v0.6.0-rc.2
Release candidate — unreleased changelog snapshot
Changed
- BREAKING API: with
server.swagger_enabled = true, the Swagger UI, its assets and/api-docs/openapi.jsonare served without an API key also whenauth.enabled = true; the API calls made from the UI still need one. - BREAKING API: operation ids of the domain endpoints are unique per engine (
kv_,json_,rel_prefix). - Default of
lsm.max_key_lengthraised from 256 to 512; adomains.max_user_key_lengththat does not fit intolsm.max_key_lengthminus the 19-byte internal domain prefix is capped with a startup warning (256/256 → 237-byte keys). - BREAKING API: Table import suffixes column names that are LuraSQL keywords with
_and rejects a keyword as table name.
Fixed
- Startup rejects zero intervals, zero channel capacities, an invalid
server.swagger_url, an unknownlog.rotationand an unusablelog.pathinstead of hanging or panicking. - BREAKING API: with
rel.enabled = falsethe relational endpoints answer 503 as documented instead of 404. - A backup schedule runs at most once per cron minute, also when the timer wakes early.
- BREAKING API:
lsm.max_value_sizenow applies to single-key KV writes (413); deleting by prefix no longer fails with 500 for keys near the length limit. - LuraSQL rejects
DISTINCT,GROUP BY,HAVING,UNION,EXCEPT,INTERSECTand join types other thanLEFT JOINwith a clear 400 instead of a misleading error. - Startup rejects a
server.swagger_urlthat would shadow the API or crash the router (/, /store-api, /health, /version, /api-docs/openapi.json, path placeholders) instead of starting a server that answers 404 to every request. - Scheduled backups resume after the system clock is set back by more than five minutes, with a warning in the log, instead of staying silent until the clock catches up.
Removed
- Config keys
storage.db_path,buffer_pool.pool_sizeandrate_limit.default_max_storage_bytes; the server no longer creates the emptyluradb.dbpage file. Aluradb.tomlthat still sets them starts with a warning per key. - BREAKING API: GET /store-api/config no longer reports these three keys.
LuraDB v0.5.1
Added
- New
[multicore].cpu_offload_threadsconfig key caps concurrent CPU offloads (0= auto). - The shipped luradb.toml documents every configuration key.
- Startup rejects out-of-range values for the remaining configuration keys.
- Startup warns about unknown configuration keys.
- New
[multicore].frontend_workersconfig key. - New
[multicore].reader_threadsand[multicore].reader_queue_capacityconfig keys. - BREAKING API: GET /store-api/metrics reports an
shmblock with snapshot publish, skip and kicked-client counters. - New
[shm].kick_blocking_client_after_secsconfig key disconnects clients that keep the shared-memory snapshot from being updated (0= off). - BREAKING API: KV keys carry an
ETag; PUT, DELETE and PATCH …/null acceptIf-Match(412 on mismatch or a missing key) andIf-None-Match: *(create only, 412 if the key exists). - BREAKING API: domains created with
require_conditional_writesreject unconditional single-key writes with 428. - New
[storage].system_dirconfig key sets the directory of the system store, which holds users, API key hashes and permissions apart from domain data. - New
[storage].wal_queue_capacityconfig key sets how many writes may wait for the storage thread. - New
[multicore].shard_queue_capacityconfig key. - Multi-shard mode:
[multicore].shardsspreads domain writes over N engine threads;0keeps the count a data directory was written with, a new directory gets cores / 4 (at most 8). luradb --migrate-shards Nchanges the shard count of a data directory offline.- The server refuses to start on a data directory that another LuraDB process uses.
- BREAKING API: Backups include relational domains (schema, rows, AUTOINCREMENT state); scope accepts
relandrel:<domain>. - Built-in MCP server with OAuth sign-in (opt-in,
[mcp]config section). storage.wal_max_sizecaps the write-ahead log of each engine (default 256 MiB); the shards holding the oldest segment flush and the segment is dropped when the cap is reached, and a segment open for five minutes is closed the same way.- The server watches free disk space and its own memory use; below configurable thresholds it logs a warning, then refuses writes with 507 and
Retry-Afterwhile reads continue, and resumes on its own; while memory is short it flushes its MemTables and returns free heap to the kernel.GET /healthreportsdegradedwith the states in a newresourcesfield, andGET /store-api/metricscarries the numbers and paths in itsresources. [resources]settingsdisk_free_warn,disk_free_block,disk_free_resume,memory_budgettake sizes and percentages.GET /healthreportsdegradedwith a newiofield (failures) while writes of a data file keep failing, andGET /store-api/metricsnames the file in itsio(path,failures).
Changed
- BREAKING Format: the write-ahead log path is now a directory of segments; earlier versions cannot open a data directory written by this version.
- The write-ahead log of each engine is kept in 64 MiB segment files under the configured path; full segments are deleted once their contents are in the data files, with no copying and no write pause.
- BREAKING Format: the write-ahead log header now records the starting sequence number; data directories opened by this version cannot be opened by earlier versions.
- Recovery after a crash replays only the write-ahead log entries that are not yet in the data files, streaming them with bounded memory.
- Write-ahead log sequence numbers continue across restarts instead of starting at 1 after a clean shutdown.
POST /oauth/registeron the MCP listener answers a missing or wrong Content-Type and malformed JSON with a JSON error (400,invalid_client_metadata).- With
mcp.public_urlunder a path, the MCP listener also serves its OAuth metadata at the RFC 8414 and RFC 9728 well-known paths. - The MCP tool
kv_getreturns a value exactly as stored, as{"value": …}withnullfor a NULL key and base64url for non-UTF-8 values. - The MCP listener limits OAuth client registrations per client IP and to 10 redirect URIs of up to 2048 characters; registrations never used to sign in expire after a day.
- The Debian package no longer starts the service on first install and prints where the config lives and how to start it; upgrades restart the service only if it is running.
- Relational domains follow the
[rate_limit]defaults instead of a fixed 1000 reads/500 writes per second. - Building the SHM snapshot of a domain larger than the data buffer no longer holds the whole domain in memory.
- Long scans, queries and imports no longer block concurrent small requests; CPU-heavy parsing runs off the engine thread.
- SHM snapshots are only rebuilt after data changes, cutting tail latency of small requests on idle servers.
- The SHM command dispatcher wakes on a per-client doorbell passed with the registration reply instead of a 10 µs idle sleep loop.
- Key listings, counts and queries no longer read unrelated recent writes.
- Key listings, counts and queries no longer read unrelated on-disk entries.
- The read path is thread-safe: readers see one consistent version of an engine's sources, and the block cache is striped.
- HTTP and TLS termination run on a multi-threaded frontend runtime; the storage engines stay on a dedicated engine thread.
- BREAKING API: requests on one connection are processed in order, HTTP/2 included — a connection serves one stream at a time, so clients need several connections for parallelism.
- Short reads are served on the connection thread; long reads run on a multi-threaded reader pool and writes stay on the engine thread.
- BREAKING: Requires Linux kernel 6.1 or newer; the server refuses to start on older kernels.
- BREAKING API: a failed
If-Matchon a JSON document answers 412 instead of 409 (also for a missing document), every 412 carries theETagof the current version, andIf-Matchmay be combined withIf-None-Match: *(If-Match is checked first). - Auth records move to the system store on first start (automatic, one-way; a downgrade needs a backup restore).
- The storage thread always runs; all write-ahead logs (KV, JSON, relational, system) are written by it with shared group commit.
io_engine.enablednow only toggles registered buffers.- Write-ahead log format v2 (LSN-framed); existing logs are upgraded automatically on first start (one-way — a downgrade needs a backup restore).
- The storage thread syncs the write-ahead logs of several engines in parallel instead of one after another.
- BREAKING API: 503 Service Unavailable with Retry-After when the server is overloaded.
- Data directory layout: engine files move into shard_0/ on first start (automatic, one-way).
- BREAKING API:
GET /healthreports per-shard status and answers 503 with statusdegradedwhen a shard does not respond. - BREAKING API:
GET /store-api/metricsanswers 503 while a data shard is not running. - BREAKING API: Watch/event stream ids carry the shard in their epoch; existing cursors resync once after the upgrade.
[io_engine].enabledhas no effect with more than one shard.- SHM snapshots are published from a consistent cut across all shards.
- BREAKING API: Backup archives use manifest format v2 (shard count, LSN cut); v1 archives remain restorable.
- The storage hub submits writes for other log files while a commit is still in flight.
- BREAKING API: domain listings return the domains the API key has permissions on instead of 403 for non-admin keys; JSON and relational domain details are readable with a domain permission.
- A failed fsync of the write-ahead log or value log stops the service with exit code 3 so the next start recovers from the write-ahead log; a start without room to recover exits with code 4, and the systemd unit does not restart after it.
- BREAKING API: writes during a disk or memory shortage answer 507 Insufficient Storage instead of 500.
- A start on a volume below the block threshold but with room for the recovery now starts with writes refused instead of exiting with code 4.
- Compaction merges SSTables as a stream and writes one output file at a time; its memory no longer grows with the size of its inputs.
- Compaction writes each data block as soon as it is complete; a compaction holds one block, the index and the Bloom filter of the file it is writing, not the whole output file.
- A data write that fails with a read-only file system, or three times in a row with another I/O error (a full disk or quota does not count), stops the service with exit code 3 so the next start recovers from the write-ahead log; the flush retries once a second instead of ten times, logs its error once and then every 60th time, and leaves no temporary files behind; the start removes temporary files an earlier run left.
- A failed sync of a newly written SSTable counts like a failed write:
/healthreports it as degraded, and the third in a row stops the service with exit code 3.
Removed
- BREAKING API: GET /store-api/config no longer reports the removed configuration keys.
- 72 undocumented tuning keys are no longer configurable; their former defaults are fixed.
Fixed
luradb --migrate-shardsno longer warns about a missing old layout when the config names the data directory both absolutely and relatively.- Snapshot reads no longer miss an older version when the key is a prefix of another key or contains bytes above 0xFD.
- Point reads no longer slow down with the size of newer SSTables that do not hold the key.
- Reads no longer miss keys while a MemTable flush or a compaction installs its result.
- Reads no longer fail or return stale values when vLog garbage collection overlaps a MemTable flush or a compaction.
expandno longer returnsnullfor a reference whose target was compacted away during the query.- Disabling the JSON engine no ...
LuraDB v0.5.0-rc.2
Release candidate — unreleased changelog snapshot
Added
- New
[multicore].cpu_offload_threadsconfig key caps concurrent CPU offloads (0= auto). - The shipped luradb.toml documents every configuration key.
- Startup rejects out-of-range values for the remaining configuration keys.
- Startup warns about unknown configuration keys.
- New
[multicore].frontend_workersconfig key. - New
[multicore].reader_threadsand[multicore].reader_queue_capacityconfig keys. - BREAKING API: GET /store-api/metrics reports an
shmblock with snapshot publish, skip and kicked-client counters. - New
[shm].kick_blocking_client_after_secsconfig key disconnects clients that keep the shared-memory snapshot from being updated (0= off). - BREAKING API: KV keys carry an
ETag; PUT, DELETE and PATCH …/null acceptIf-Match(412 on mismatch or a missing key) andIf-None-Match: *(create only, 412 if the key exists). - BREAKING API: domains created with
require_conditional_writesreject unconditional single-key writes with 428. - New
[storage].system_dirconfig key sets the directory of the system store, which holds users, API key hashes and permissions apart from domain data. - New
[storage].wal_queue_capacityconfig key sets how many writes may wait for the storage thread. - New
[multicore].shard_queue_capacityconfig key. - Multi-shard mode:
[multicore].shardsspreads domain writes over N engine threads;0keeps the count a data directory was written with, a new directory gets cores / 4 (at most 8). luradb --migrate-shards Nchanges the shard count of a data directory offline.- The server refuses to start on a data directory that another LuraDB process uses.
- BREAKING API: Backups include relational domains (schema, rows, AUTOINCREMENT state); scope accepts
relandrel:<domain>. - Built-in MCP server with OAuth sign-in (opt-in,
[mcp]config section). storage.wal_max_sizecaps the write-ahead log of each engine (default 256 MiB); the shards holding the oldest segment flush and the segment is dropped when the cap is reached, and a segment open for five minutes is closed the same way.- The server watches free disk space and its own memory use; below configurable thresholds it logs a warning, then refuses writes with 507 and
Retry-Afterwhile reads continue, and resumes on its own; while memory is short it flushes its MemTables and returns free heap to the kernel.GET /healthreportsdegradedwith the states in a newresourcesfield, andGET /store-api/metricscarries the numbers and paths in itsresources. [resources]settingsdisk_free_warn,disk_free_block,disk_free_resume,memory_budgettake sizes and percentages.GET /healthreportsdegradedwith a newiofield (failures) while writes of a data file keep failing, andGET /store-api/metricsnames the file in itsio(path,failures).
Changed
- BREAKING Format: the write-ahead log path is now a directory of segments; earlier versions cannot open a data directory written by this version.
- The write-ahead log of each engine is kept in 64 MiB segment files under the configured path; full segments are deleted once their contents are in the data files, with no copying and no write pause.
- BREAKING Format: the write-ahead log header now records the starting sequence number; data directories opened by this version cannot be opened by earlier versions.
- Recovery after a crash replays only the write-ahead log entries that are not yet in the data files, streaming them with bounded memory.
- Write-ahead log sequence numbers continue across restarts instead of starting at 1 after a clean shutdown.
POST /oauth/registeron the MCP listener answers a missing or wrong Content-Type and malformed JSON with a JSON error (400,invalid_client_metadata).- With
mcp.public_urlunder a path, the MCP listener also serves its OAuth metadata at the RFC 8414 and RFC 9728 well-known paths. - The MCP tool
kv_getreturns a value exactly as stored, as{"value": …}withnullfor a NULL key and base64url for non-UTF-8 values. - The MCP listener limits OAuth client registrations per client IP and to 10 redirect URIs of up to 2048 characters; registrations never used to sign in expire after a day.
- The Debian package no longer starts the service on first install and prints where the config lives and how to start it; upgrades restart the service only if it is running.
- Relational domains follow the
[rate_limit]defaults instead of a fixed 1000 reads/500 writes per second. - Building the SHM snapshot of a domain larger than the data buffer no longer holds the whole domain in memory.
- Long scans, queries and imports no longer block concurrent small requests; CPU-heavy parsing runs off the engine thread.
- SHM snapshots are only rebuilt after data changes, cutting tail latency of small requests on idle servers.
- The SHM command dispatcher wakes on a per-client doorbell passed with the registration reply instead of a 10 µs idle sleep loop.
- Key listings, counts and queries no longer read unrelated recent writes.
- Key listings, counts and queries no longer read unrelated on-disk entries.
- The read path is thread-safe: readers see one consistent version of an engine's sources, and the block cache is striped.
- HTTP and TLS termination run on a multi-threaded frontend runtime; the storage engines stay on a dedicated engine thread.
- BREAKING API: requests on one connection are processed in order, HTTP/2 included — a connection serves one stream at a time, so clients need several connections for parallelism.
- Short reads are served on the connection thread; long reads run on a multi-threaded reader pool and writes stay on the engine thread.
- BREAKING: Requires Linux kernel 6.1 or newer; the server refuses to start on older kernels.
- BREAKING API: a failed
If-Matchon a JSON document answers 412 instead of 409 (also for a missing document), every 412 carries theETagof the current version, andIf-Matchmay be combined withIf-None-Match: *(If-Match is checked first). - Auth records move to the system store on first start (automatic, one-way; a downgrade needs a backup restore).
- The storage thread always runs; all write-ahead logs (KV, JSON, relational, system) are written by it with shared group commit.
io_engine.enablednow only toggles registered buffers.- Write-ahead log format v2 (LSN-framed); existing logs are upgraded automatically on first start (one-way — a downgrade needs a backup restore).
- The storage thread syncs the write-ahead logs of several engines in parallel instead of one after another.
- BREAKING API: 503 Service Unavailable with Retry-After when the server is overloaded.
- Data directory layout: engine files move into shard_0/ on first start (automatic, one-way).
- BREAKING API:
GET /healthreports per-shard status and answers 503 with statusdegradedwhen a shard does not respond. - BREAKING API:
GET /store-api/metricsanswers 503 while a data shard is not running. - BREAKING API: Watch/event stream ids carry the shard in their epoch; existing cursors resync once after the upgrade.
[io_engine].enabledhas no effect with more than one shard.- SHM snapshots are published from a consistent cut across all shards.
- BREAKING API: Backup archives use manifest format v2 (shard count, LSN cut); v1 archives remain restorable.
- The storage hub submits writes for other log files while a commit is still in flight.
- BREAKING API: domain listings return the domains the API key has permissions on instead of 403 for non-admin keys; JSON and relational domain details are readable with a domain permission.
- A failed fsync of the write-ahead log or value log stops the service with exit code 3 so the next start recovers from the write-ahead log; a start without room to recover exits with code 4, and the systemd unit does not restart after it.
- BREAKING API: writes during a disk or memory shortage answer 507 Insufficient Storage instead of 500.
- A start on a volume below the block threshold but with room for the recovery now starts with writes refused instead of exiting with code 4.
- Compaction merges SSTables as a stream and writes one output file at a time; its memory no longer grows with the size of its inputs.
- Compaction writes each data block as soon as it is complete; a compaction holds one block, the index and the Bloom filter of the file it is writing, not the whole output file.
- A data write that fails with a read-only file system, or three times in a row with another I/O error (a full disk or quota does not count), stops the service with exit code 3 so the next start recovers from the write-ahead log; the flush retries once a second instead of ten times, logs its error once and then every 60th time, and leaves no temporary files behind; the start removes temporary files an earlier run left.
- A failed sync of a newly written SSTable counts like a failed write:
/healthreports it as degraded, and the third in a row stops the service with exit code 3.
Removed
- BREAKING API: GET /store-api/config no longer reports the removed configuration keys.
- 72 undocumented tuning keys are no longer configurable; their former defaults are fixed.
Fixed
- Snapshot reads no longer miss an older version when the key is a prefix of another key or contains bytes above 0xFD.
- Point reads no longer slow down with the size of newer SSTables that do not hold the key.
- Reads no longer miss keys while a MemTable flush or a compaction installs its result.
- Reads no longer fail or return stale values when vLog garbage collection overlaps a MemTable flush or a compaction.
expandno longer returnsnullfor a reference whose target was compacted away during the query.- Disabling the JSON engine no longer permanently clears JSON references in relational tables.
- Startup detects data paths ...
LuraDB v0.4.0
Added
-
API: added
POST /store-api/rel/{domain}/tables/from-file— creates a relational table from an uploaded CSV/TSV file with inferred column types (INTEGER/REAL/BOOLEAN/TIMESTAMP/TEXT) and imports its rows, reportingimported/failed/per-row errors like the JSON bulk load; new[rel].import_body_limit_bytesconfig key (default 64 MiB). -
BREAKING API:
GET /store-api/auth/usersresponses now include apermissionsarray per user ({domain, store_type, access}), mirroring the write-endpoint vocabulary. -
BREAKING API: added
GET /store-api/auth/whoami, returning the caller's identity ({name, role}) for any authenticated caller — not admin-only.roleis"Admin","User", or a pseudo-role ("TrustedPeer","Disabled"). -
BREAKING API: added
GET /store-api/kv/{domain}/keys/{key}/meta, returning a key's TTL expiry and last-modified time ({expires_at, last_modified_at}) without reading its value.GET /store-api/kv/{domain}/keys/{key}now also carries anX-Expires-Atresponse header when the key has a TTL. -
BREAKING API: added
GET /store-api/kv/{domain}/count(optional?prefix=) andGET /store-api/rel/{domain}/tables/{table}/count, each returning{"count": N}— a full key/row scan, same cost as listing. -
BREAKING API:
GET /store-api/kv/{domain}/watchSSE events now carry anid:field, and the endpoint acceptsLast-Event-ID(header, takes precedence) or?last_event_id=(query) to resume gaplessly from an in-memory replay ring; a newresetevent type is emitted whenever gapless resume can't be guaranteed (window exceeded, server restart, or a lagged consumer). New[lsm].watch_replay_buffer_sizeconfig key controls the ring size (0disables resume). -
BREAKING API: added
GET /store-api/events, an SSE stream of lifecycle/DDL events across the KV, JSON and relational engines (domain created/deleted/purged; rel table/view/index DDL; JSON index DDL) — admin-only, no per-key data events. Sameid:/Last-Event-ID/resetresume mechanism as the KV watch, with its own tag and sequence. New[events]config section (channel_capacity,replay_buffer_size). -
BREAKING API:
PUT /store-api/json/{domain}/documents/{key}now supports create-only writes viaIf-None-Match: *, answering412 Precondition Failedif the document already exists; only the literal*is supported, and combining it withIf-Matchanswers400. -
BREAKING API: added
DELETE /store-api/kv/{domain}/keys?prefix={p}&contains={s}, deleting every matching key in one atomic write batch and returning{"deleted": N};prefixis required and non-empty (a domain-emptying request still needs the admin-only domain delete), and a selection over the new[domains].max_bulk_delete_keyslimit (default 10,000) answers413with nothing deleted. -
BREAKING API:
POST /store-api/json/{domain}/documents,PUT /store-api/json/{domain}/documents/{key}, andGET /store-api/json/{domain}/documents/{key}now document their response body asDocumentResponse(_key,_version, plus the document's own fields) in the OpenAPI contract — the JSON returned on the wire is unchanged. -
BREAKING API:
GET /store-api/metricsnow includes anenginesblock (kv/json/rel), each withread_ops,write_ops,read_latency_us_p50/p95/p99,write_latency_us_p50/p95/p99, andwindow_secs— per-engine op counts and latency percentiles over the rolling metrics window, alongside the existing KV-onlydomains[]. -
Optional CORS support via the new
[cors]config section — an opt-inCorsLayer(exact origin allow-list, or"*") lets browser clients call the API directly without a proxy in front; off by default. -
BREAKING API: added
GET /store-api/config, returning the effective configuration of the running process (config_path,config_file_loaded,config) — admin-only; the admin API key is redacted fromconfig, everything else is the same field names as the TOML file. -
Startup now fails fast when
max_value_sizeormax_key_lengthof any engine's[lsm]block exceed the WAL recovery field cap — previously such a config wrote WAL records that only failed the next restart's recovery. -
BREAKING API: JSON document-store OpenAPI contract now documents
410 Goneon all document/index/search/bulk/reindex routes,If-Matchas a header parameter onPUT/DELETE …/documents/{key}, theETagresponse header onGET …/documents/{key},DocumentListResponse/SearchResponsedocument lists typed asDocumentResponse[], andtext/plainstring bodies on every 4xx/5xx response in the JSON API. -
BREAKING API: every documented 4xx/5xx error response across the rest of the REST API (KV, domains, relational store/browse/rows, auth, backup/restore, logs, metrics, global events) now documents its body as a
text/plainstring in the OpenAPI contract, same as the JSON API above — wire format unchanged, previously undocumented; a new contract test enforces this on every current and future route. -
BREAKING API:
POST /store-api/json/{domain}/documentsandPUT /store-api/json/{domain}/documents/{key}now reject a top-level_key,_version, or_contentfield in the request body with400— these are reserved store-metadata names that a document could previously carry but never actually round-trip through: shadowed by the same-named metadata on every read, and unsafe across NDJSON export/re-import.POST /store-api/json/{domain}/bulk(and restore, which shares the same import path) now counts such a line as a per-document import error (failed/errors) instead of importing it; nested occurrences (e.g.{"a": {"_key": 1}}) are unaffected, and documents written before this change stay stored and readable as before. -
Releases now ship a machine-readable
changelog.jsonasset alongside the existing changelog notes.
Security
- Rel: LIKE matching no longer allocates a table sized by pattern × text length.
- Rel: pathologically self-similar LIKE patterns now abort with an error instead of monopolizing a CPU core per row.
- Auth: rotating an API key now immediately invalidates the previous one — it used to stay valid in the cache until a second restart.
- BREAKING Rel: cross-engine KVREF/JSONREF links now require read access to the target KV/JSON domain.
/sqlexpand of a column the caller can't read now returnsnullinstead of the resolved value; INSERT/UPDATE (via/sqlor row writes) with such a link now answers 403 instead of succeeding or 409. - The server refuses to start with authentication disabled on a non-loopback bind — a config without
[auth], or a bind to0.0.0.0/::withauth.enabled = false, previously started silently with unauthenticated, network-wide access. - BREAKING API: the Swagger UI and
/api-docs/openapi.jsonnow require a valid API key whenauth.enabled = true(previously open regardless — the same server-version fingerprint thatGET /versionwas hardened against was still readable from the OpenAPI contract).server.swagger_enablednow defaults tofalse. - The Docker try image no longer embeds a generated admin key in an image layer — the key is now generated in the running container on first start instead.
- Rel: a CSV/TSV import with a huge column header no longer stalls the whole server — the column limit is now enforced before the header is processed.
Changed
- BREAKING API:
POST /store-api/auth/users/{name}/permissionsnow checks domain existence forjson/relstore types when their engine is active — a missing domain now answers404(previously200), matching the existingkvbehavior. New opt-in query parameter?allow_missing=trueskips the existence check for all three store types (pre-provisioning), now includingkvfor the first time; domain name validation (400) applies tojson/relunconditionally and tokvonly whenallow_missing=true. - BREAKING
server.bind_addressnow defaults to127.0.0.1(previously0.0.0.0). Only affects a start without a config file, or one that omitsbind_address; both shipped configs (luradb.toml,packaging/luradb.toml) already bind loopback explicitly. - BREAKING API:
GET /store-api/kv/{domain}/keysnow returns a paginated envelope ({keys, total, offset, limit}) instead of a bare array, and accepts newcontains,limit(default 1000, max 10000), andoffsetquery parameters. - JSON document writes on different keys no longer serialize behind one engine-global lock.
- KV: expired keys are now removed proactively and emit a
deleteevent — a background TTL sweeper tombstones them instead of leaving them to the next compaction, so watch subscribers see the expiry and the space comes back earlier. New[ttl_sweeper]config section (enabled,interval_secs,batch_size);enabled = falserestores the previous purely lazy behavior.
Fixed
- SSTable: a corrupted bloom filter block (empty bit array with a non-zero hash count) fails with an error instead of a panic.
- LSM: shutdown with a failed flush no longer truncates the WAL.
- LSM: startup fails loudly instead of silently skipping an unopenable SSTable.
- LSM: a restarted engine now seeds its clock from the recovered WAL and manifest — after a backwards system-clock step it no longer hides existing data or buries a rewritten key under its older version.
- LSM: a concurrent flush/compaction/GC save can no longer persist a stale manifest.
- LSM: a corrupt WAL length field fails recovery instead of allocating up to 4 GiB.
- Rel: a
SELECT … LIMITwithout ORDER BY no longer returns a short page when concurrent inserts land in the capped scan window. - Rel: reads resolve their candidate rows against the statement snapshot on every access path, so concurrently deleted rows no longer vanish mid-query and the unindexed-join budget counts only visible rows.
- LSM: a MemTable rotation can no longer strand an in-flight write...
LuraDB v0.3.1
Fixed
- KV: a TTL of
nseconds now holds for at leastnseconds. Expiry stamps are whole seconds and the sub-second remainder was dropped, so entries expired up to a second early — a 1-second TTL could be gone within milliseconds.
LuraDB v0.3.0
Added
- API: logical backup & restore — consistent NDJSON export per scope (
all, engine, single domain) with on-demand jobs, cron schedules with retention, download/upload, and restore with optional domain remapping (admin-only, opt-in viabackup.enabled). Covers the KV and JSON engines only — relational data is not included yet. - API: read-only log access —
GET /store-api/logs(tail withlines/q/file) andGET /store-api/logs/files(file listing), admin-only, opt-in vialog.http_access. packaging/docker/: Docker try-setup (Dockerfile, compose.yaml, entrypoint) that installs a user-provided.debfromtarget/debian/to run LuraDB viadocker compose up -dwithout a Rust toolchain or Linux host.
Fixed
- API:
/healthnow reports the crate version (previously hardcoded0.1.0).
LuraDB v0.2.1
Security
- Replaced the retired
rustls-pemfiledependency withrustls-pki-typesPEM loading (RUSTSEC-2025-0134).
LuraDB v0.1.1
Security
- Security scans: RUSTSEC-2026-0235 (rkyv 0.7) ignored as not exploitable in LuraDB.
LuraDB v0.1.0
Added
- Initial release of the LuraDB server: key-value, JSON document, and slim-relational engines behind a single REST API, with token-based authentication, TLS/reverse-proxy support, and a Debian package with systemd integration.
Security
- Removed the unmaintained
bincode1.x dependency (declared but unused) and droppedproc-macro-errorby upgrading utoipa to 5 — resolves the RUSTSEC-2025-0141 and RUSTSEC-2024-0370 scan exceptions.
LuraDB v0.1.0-rc.1
Release candidate — unreleased changelog snapshot
Added
- Initial release of the LuraDB server: key-value, JSON document, and slim-relational engines behind a single REST API, with token-based authentication, TLS/reverse-proxy support, and a Debian package with systemd integration.