{"id":47297765,"url":"https://github.com/lux-db/lux","last_synced_at":"2026-06-05T01:01:17.502Z","repository":{"id":344652957,"uuid":"1182588635","full_name":"lux-db/lux","owner":"lux-db","description":"A Redis-compatable key-value store. Up to 10x faster. Native vector support.","archived":false,"fork":false,"pushed_at":"2026-05-30T18:40:10.000Z","size":5950,"stargazers_count":258,"open_issues_count":0,"forks_count":18,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-30T20:15:59.192Z","etag":null,"topics":["database","dragonflydb","embeddings","lux","postgres","redis","rust","supabase","vector"],"latest_commit_sha":null,"homepage":"https://luxdb.dev","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lux-db.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-15T18:07:32.000Z","updated_at":"2026-05-30T18:40:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/lux-db/lux","commit_stats":null,"previous_names":["lux-db/lux"],"tags_count":42,"template":false,"template_full_name":null,"purl":"pkg:github/lux-db/lux","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lux-db%2Flux","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lux-db%2Flux/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lux-db%2Flux/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lux-db%2Flux/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lux-db","download_url":"https://codeload.github.com/lux-db/lux/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lux-db%2Flux/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33926275,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","dragonflydb","embeddings","lux","postgres","redis","rust","supabase","vector"],"created_at":"2026-03-16T19:04:10.557Z","updated_at":"2026-06-05T01:01:17.480Z","avatar_url":"https://github.com/lux-db.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"logo.png\" alt=\"Lux\" width=\"120\" height=\"120\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eLux\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eA Redis-compatible key-value store. Up to 10x faster.\u003c/strong\u003e\u003cbr/\u003e\n  Multi-threaded. Built-in vector search, time series, realtime key subscriptions, and GEO. BullMQ-compatible. Written in Rust. MIT licensed forever.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/lux-db/lux/actions/workflows/test.yml\"\u003e\u003cimg src=\"https://github.com/lux-db/lux/actions/workflows/test.yml/badge.svg\" alt=\"Tests\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/lux-db/lux/releases/latest\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/lux-db/lux\" alt=\"Release\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/lux-db/lux/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"MIT License\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://luxdb.dev\"\u003eLux Cloud\u003c/a\u003e \u0026middot;\n  \u003ca href=\"https://luxdb.dev/vs/redis\"\u003eBenchmarks\u003c/a\u003e \u0026middot;\n  \u003ca href=\"https://luxdb.dev/architecture\"\u003eArchitecture\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## Why Lux?\n\nRedis is single-threaded by design. Antirez made that choice in 2009 because it eliminates all locking, race conditions, and concurrency bugs. For most workloads, the bottleneck is network I/O, not CPU, so a single-threaded event loop is fast enough. It was a brilliant simplification.\n\nBut it has a ceiling. Once you saturate one core, that's it. Redis can't use the other 15 cores on your machine. The official answer is to run multiple Redis instances and shard at the client level (Redis Cluster), which adds significant operational complexity.\n\nLux takes the opposite approach: a **sharded concurrent architecture** that safely uses all your cores in a single process. Each key maps to one of N shards, each protected by a `parking_lot` RwLock. Reads never block reads. Writes only block the single shard they touch. Tokio's async runtime handles thousands of connections across all cores. The result: single-digit microsecond latency at low concurrency (matching Redis), and linear throughput scaling as you add cores and pipeline depth (where Redis flatlines).\n\n\"Doesn't multi-threading introduce the bugs Redis avoided?\" No. Lux's concurrency is at the shard level, not the command level. Each command acquires a single shard lock, does its work, and releases. There are no cross-shard locks, no lock ordering issues, no deadlocks. The only shared mutable state is inside shards, and the RwLock makes that safe. MULTI/EXEC transactions use WATCH-based optimistic concurrency (shard versioning) rather than global locks, matching what Redis clients actually rely on.\n\nPoint your existing Redis client at Lux. Most workloads just work.\n\n**Works with every Redis client** -- ioredis, redis-py, go-redis, Jedis, redis-rb, BullMQ. Zero code changes.\n\n### Benchmarks\n\n`redis-benchmark`, 50 clients, 1M requests, pipeline=64. Sequential runs (one server at a time) on a 32-core Intel i9-14900K, 128GB RAM, Ubuntu 24.04.\n\n| Command | Lux | Redis 8.4.2 | Lux/Redis |\n|---------|-----|-------------|-----------|\n| SET | 10.2M | 3.4M | **3.0x** |\n| GET | 12.0M | 4.7M | **2.6x** |\n| INCR | 6.3M | 4.0M | **1.6x** |\n| LPUSH | 6.5M | 3.3M | **2.0x** |\n| RPUSH | 6.4M | 3.7M | **1.7x** |\n| LPOP | 11.6M | 3.0M | **3.9x** |\n| RPOP | 11.1M | 3.3M | **3.4x** |\n| SADD | 7.2M | 4.1M | **1.8x** |\n| HSET | 6.8M | 3.3M | **2.0x** |\n| SPOP | 12.2M | 4.5M | **2.7x** |\n| ZADD | 7.0M | 3.1M | **2.3x** |\n| ZPOPMIN | 11.5M | 5.3M | **2.2x** |\n| GEOPOS | 5.26M | 2.60M | **2.0x** |\n| GEODIST | 6.67M | 2.53M | **2.6x** |\n| GEOSEARCH (500km) | 4.44M | 559K | **8.0x** |\n| GEOSEARCH (5000km) | 200K | 20K | **10.0x** |\n\nLux beats Redis on every supported command. At pipeline=1, both are network-bound and roughly equal. The gap grows with pipeline depth because Lux batches same-shard commands under a single lock while Redis processes sequentially on one core. GEO commands see the biggest gains because GEOSEARCH parallelizes across shards while Redis scans single-threaded.\n\nFull results including SET scaling by pipeline depth (up to **5.8x** at pipeline=512) in [BENCHMARKS.md](BENCHMARKS.md). Reproduce with `./bench.sh`.\n\n## Lux Cloud\n\nDon't want to manage infrastructure? **[Lux Cloud](https://luxdb.dev)** is managed Lux hosting. Deploy in seconds, connect with any Redis client. Includes BullMQ queue dashboard, agent memory MCP server, persistence, monitoring, and web console.\n\n## Features\n\n- **200+ commands** -- strings, lists, hashes, sets, sorted sets, streams, vectors, geo, time series, tables, HyperLogLog, bitops, pub/sub, transactions\n- **Relational tables** -- TCREATE, TINSERT, TSELECT, TUPDATE (WHERE), TDELETE (WHERE), TALTER with typed fields (str, int, float, bool, timestamp, uuid), unique constraints, foreign keys, joins, WHERE/ORDER BY/LIMIT. Structured data without standing up Postgres\n- **Realtime key subscriptions** -- KSUB/KUNSUB: subscribe to key patterns, receive events when matching keys are mutated. Zero overhead when unused. No global config flags, no separate services. Unlike Redis keyspace notifications which tax every write globally, KSUB is surgical and async\n- **Native time series** -- TSADD, TSGET, TSRANGE, TSMRANGE with aggregation (avg, sum, min, max, count, std), retention policies, and label-based filtering. No modules, no sidecars. TSGET 4x faster than Redis GET\n- **Native vector search** -- VSET, VGET, VSEARCH with cosine similarity and metadata filtering. No extensions, no sidecars\n- **GEO commands** -- GEOADD, GEOSEARCH, GEODIST, GEOPOS, GEOHASH, GEORADIUS with up to 10x faster spatial queries\n- **LRU eviction** -- maxmemory with allkeys-lru, volatile-lru, allkeys-random, volatile-random policies\n- **BullMQ compatible** -- blocking commands, streams, Lua scripting with cmsgpack/cjson\n- **Lua scripting** -- EVAL, EVALSHA, SCRIPT with redis.call/pcall, cmsgpack, and cjson\n- **Redis Streams** -- XADD, XREAD, XREADGROUP, XACK, consumer groups, blocking reads\n- **Blocking commands** -- BLPOP, BRPOP, BLMOVE, BZPOPMIN, BZPOPMAX\n- **HTTP REST API** -- built-in JSON API on a separate port, 174K ops/sec, Bearer auth, CORS\n- **RESP2 protocol** -- compatible with every Redis client\n- **Multi-threaded** -- auto-tuned shards, parking_lot RwLocks, tokio async runtime\n- **Zero-copy parser** -- RESP arguments are byte slices into the read buffer\n- **Pipeline batching** -- consecutive same-shard commands batched under a single lock\n- **Persistence** -- automatic snapshots, write-ahead log (WAL) with CRC32 checksums, tiered hot/cold storage with automatic eviction to disk\n- **Auth** -- password authentication via `LUX_PASSWORD`\n- **Pub/Sub** -- SUBSCRIBE, PSUBSCRIBE, PUBLISH, plus KSUB/KUNSUB for realtime key change events\n- **TTL support** -- EX, PX, EXPIRE, PEXPIRE, PERSIST, TTL, PTTL\n- **MIT licensed** -- no license rug-pulls, unlike Redis (RSALv2/SSPL)\n\n## Quick Start\n\n```bash\ncargo build --release\n./target/release/lux\n```\n\nLux starts on `0.0.0.0:6379` by default. Connect with any Redis client using `lux://` or `redis://`:\n\n\u003e **Protocol note:** `lux://` is the primary protocol for the Lux SDK and luxctl CLI. When using third-party Redis clients (ioredis, redis-py, go-redis) directly, use `redis://` since they don't recognize `lux://`. Both connect to the same server.\n\n```bash\nredis-cli\n\u003e SET hello world\nOK\n\u003e GET hello\n\"world\"\n```\n\n### Docker\n\n```bash\ndocker run -d -p 6379:6379 ghcr.io/lux-db/lux:latest\n```\n\n### Docker Compose\n\n```bash\ndocker compose up -d        # start\ndocker compose up -d --build  # rebuild \u0026 start\ndocker compose down         # stop\n```\n\n### Vector Search\n\nLux has native vector storage and cosine similarity search. No extensions, no sidecars, no separate services.\n\n```bash\n# Store vectors with optional metadata\nredis-cli VSET doc:1 3 0.1 0.2 0.3 META '{\"title\":\"hello world\"}'\nredis-cli VSET doc:2 3 0.9 0.1 0.0 META '{\"title\":\"another doc\"}'\n\n# Find the 5 nearest neighbors\nredis-cli VSEARCH 3 0.1 0.2 0.3 K 5\n\n# Search with metadata filtering\nredis-cli VSEARCH 3 0.1 0.2 0.3 K 5 FILTER title \"hello world\" META\n\n# Count vectors\nredis-cli VCARD\n```\n\nSub-millisecond search at 10,000 vectors with HNSW indexing. Built for AI agent memory, RAG, and semantic search.\n\n### Time Series\n\nBuilt-in time series with retention policies, label-based filtering, and aggregation. No modules required.\n\n```bash\n# Add samples with labels\nredis-cli TSADD cpu:host1 '*' 72.5 RETENTION 86400000 LABELS host server1 metric cpu\nredis-cli TSADD cpu:host1 '*' 75.0\nredis-cli TSADD cpu:host1 '*' 68.2\n\n# Get latest sample\nredis-cli TSGET cpu:host1\n\n# Query range with aggregation (1-hour average)\nredis-cli TSRANGE cpu:host1 - + AGGREGATION avg 3600000\n\n# Query across all series matching labels\nredis-cli TSMRANGE - + FILTER host=server1\n\n# Batch insert across multiple series\nredis-cli TSMADD cpu:host1 '*' 72.5 mem:host1 '*' 45.0 disk:host1 '*' 82.1\n```\n\nTSGET runs at 18M ops/sec at high pipeline. Supports avg, sum, min, max, count, first, last, range, std.p, std.s, var.p, var.s aggregation functions.\n\n### Realtime Key Subscriptions (KSUB)\n\nSubscribe to key mutation events by pattern. When any client writes to a matching key, subscribers receive a realtime notification with the key name and operation. No polling, no keyspace notification config, no separate service.\n\n```bash\n# Client A: subscribe to all user key mutations\nredis-cli\n\u003e KSUB user:*\n\n# Client B: write some data\nredis-cli\n\u003e SET user:1 alice\n\u003e HSET user:2 name bob\n\u003e DEL user:1\n\n# Client A receives:\n# [\"kmessage\", \"user:*\", \"user:1\", \"set\"]\n# [\"kmessage\", \"user:*\", \"user:2\", \"hset\"]\n# [\"kmessage\", \"user:*\", \"user:1\", \"del\"]\n```\n\nEvents are `[\"kmessage\", pattern, key, operation]`. Operations are lowercase command names: `set`, `del`, `lpush`, `hset`, `zadd`, `tsadd`, etc.\n\n**How it differs from Redis keyspace notifications:**\n- Redis requires a global `notify-keyspace-events` config flag that adds overhead to every write, even if nobody is listening\n- KSUB has zero overhead when no subscribers exist (single atomic check)\n- When subscribers exist, event dispatch is fully async -- writes enqueue to a lock-free channel and a background task handles matching and delivery. The write path never blocks on subscriber fanout\n\nBuilt for reactive applications, cache invalidation, live dashboards, and any use case where you need to react to data changes without polling.\n\n### Tables\n\nBuilt-in relational tables with typed fields, indexes, unique constraints, foreign keys, and joins.\n\n```bash\n# Create a table with typed fields\nredis-cli TCREATE users \"id INT PRIMARY KEY,\" \"name STR,\" \"email STR UNIQUE,\" \"age INT,\" \"active BOOL\"\n\n# Insert rows (* auto-generates timestamp)\nredis-cli TINSERT users name Alice email alice@example.com age 28 active true created_at *\nredis-cli TINSERT users name Bob email bob@example.com age 35 active false created_at *\n\n# Query with WHERE, ORDER BY, LIMIT\nredis-cli TSELECT '*' FROM users WHERE age '\u003e' 25 ORDER BY age DESC LIMIT 10\n\n# Foreign keys and joins\nredis-cli TCREATE posts \"id INT PRIMARY KEY,\" \"title STR,\" \"author_id INT REFERENCES users(id)\"\nredis-cli TINSERT posts id 1 title \"Hello World\" author_id 1\nredis-cli TSELECT '*' FROM posts p JOIN users u ON p.author_id = u.id\n\n# Update and delete by predicates\nredis-cli TUPDATE users SET active true WHERE id = 1\nredis-cli TDELETE FROM users WHERE id = 2\n\n# Alter tables\nredis-cli TALTER users ADD role STR\nredis-cli TALTER users DROP role\n```\n\nField types: `STR`, `INT`, `FLOAT`, `BOOL`, `TIMESTAMP`, `UUID`.\nUse SQL-style constraints like `UNIQUE`, `PRIMARY KEY`, and `REFERENCES table(field)`.\n\n### CLI\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/lux-db/lux/main/cli/install.sh | sh\n```\n\n```bash\nluxctl login                              # authenticate with a lux_ token\nluxctl projects                           # list projects\nluxctl create my-app --accept-charges     # create a new project\nluxctl status my-app                      # show status and metrics\nluxctl exec my-app SET hello world        # run a command\nluxctl logs my-app                        # fetch logs\nluxctl restart my-app                     # restart instance\nluxctl connect my-app                     # interactive REPL via cloud\nluxctl connect lux://localhost:6379       # connect to local instance\nluxctl destroy my-app --accept-consequences  # delete project\n```\n\nSee [cli/README.md](cli/README.md) for full installation and usage docs.\n\n### SDK\n\n```bash\nbun i @luxdb/sdk\n```\n\n```typescript\nimport { Lux } from \"@luxdb/sdk\"\n\nconst db = new Lux(\"lux://localhost:6379\")\n\nawait db.set(\"hello\", \"world\")\n\nawait db.vset(\"doc:1\", embedding, { metadata: { title: \"my doc\" } })\nconst results = await db.vsearch(queryEmbedding, { k: 5, meta: true })\n\nawait db.tsadd(\"cpu:host1\", '*', 72.5, { labels: { host: \"server1\" } })\nconst latest = await db.tsget(\"cpu:host1\")\nconst range = await db.tsrange(\"cpu:host1\", '-', '+', {\n  aggregation: { type: 'avg', bucketSize: 3600000 }\n})\n\nconst sub = db.ksub([\"user:*\"], (event) =\u003e {\n  console.log(`${event.key} was ${event.operation}`)\n})\n```\n\nExtends ioredis with typed methods for vectors, time series, and realtime key subscriptions. All standard Redis commands work as usual.\n\n### HTTP REST API\n\nLux has a built-in HTTP/JSON API. Set `LUX_HTTP_PORT` to enable it alongside the RESP protocol. Every data primitive gets its own RESTful routes.\n\n```bash\nLUX_HTTP_PORT=8080 ./target/release/lux\n```\n\n**Key-Value:**\n```bash\ncurl http://localhost:8080/v1/kv/mykey                    # GET\ncurl -X PUT http://localhost:8080/v1/kv/mykey \\\n  -d '{\"value\":\"hello\",\"ex\":3600}'                        # SET (with optional TTL)\ncurl -X DELETE http://localhost:8080/v1/kv/mykey           # DEL\ncurl -X POST http://localhost:8080/v1/kv/counter/incr      # INCR\ncurl http://localhost:8080/v1/kv/myhash/hash               # HGETALL\ncurl http://localhost:8080/v1/kv/mylist/list                # LRANGE\ncurl http://localhost:8080/v1/kv/myset/set                 # SMEMBERS\ncurl http://localhost:8080/v1/kv/myzset/zset               # ZRANGEBYSCORE\n```\n\n**Tables:**\n```bash\ncurl -X POST http://localhost:8080/v1/tables \\\n  -d '{\"name\":\"users\",\"columns\":[\"id INT PRIMARY KEY\",\"name STR\",\"age INT\"]}'   # TCREATE\ncurl http://localhost:8080/v1/tables                        # TLIST\ncurl -X POST http://localhost:8080/v1/tables/users \\\n  -d '{\"name\":\"Alice\",\"age\":\"28\"}'                          # TINSERT\ncurl 'http://localhost:8080/v1/tables/users?where=age\u003e25\u0026order=name\u0026limit=10'  # TSELECT\ncurl http://localhost:8080/v1/tables/users/1                # row lookup endpoint\ncurl -X PUT http://localhost:8080/v1/tables/users/1 \\\n  -d '{\"name\":\"Alicia\"}'                                    # TUPDATE ... WHERE id = 1\ncurl -X DELETE http://localhost:8080/v1/tables/users/1      # TDELETE FROM ... WHERE id = 1\n```\n\n**Time Series:**\n```bash\ncurl -X POST http://localhost:8080/v1/ts/cpu:host1 \\\n  -d '{\"value\":72.5,\"labels\":{\"host\":\"server1\"}}'          # TSADD\ncurl http://localhost:8080/v1/ts/cpu:host1/latest           # TSGET\ncurl 'http://localhost:8080/v1/ts/cpu:host1?from=-\u0026to=+\u0026agg=avg\u0026bucket=3600000'  # TSRANGE\ncurl http://localhost:8080/v1/ts/cpu:host1/info             # TSINFO\n```\n\n**Vectors:**\n```bash\ncurl -X POST http://localhost:8080/v1/vectors/doc:1 \\\n  -d '{\"vector\":[0.1,0.2,0.3],\"metadata\":{\"title\":\"hello\"}}'  # VSET\ncurl http://localhost:8080/v1/vectors/doc:1                     # VGET\ncurl -X POST http://localhost:8080/v1/vectors/search \\\n  -d '{\"vector\":[0.1,0.2,0.3],\"k\":5}'                         # VSEARCH\ncurl http://localhost:8080/v1/vectors                            # VCARD\n```\n\n**Exec (any command):**\n```bash\ncurl -X POST http://localhost:8080/v1/exec \\\n  -d '{\"command\":[\"HSET\",\"user:1\",\"name\",\"alice\"]}'\n```\n\nAuth via `Authorization: Bearer \u003cpassword\u003e` when `LUX_PASSWORD` is set. CORS enabled by default. 174K ops/sec at 256 concurrent connections with keep-alive.\n\n### Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `LUX_PORT` | `6379` | TCP port |\n| `LUX_HTTP_PORT` | (disabled) | HTTP API port (set to enable) |\n| `LUX_PASSWORD` | (none) | Enable AUTH (applies to both RESP and HTTP) |\n| `LUX_DATA_DIR` | `.` | Snapshot directory |\n| `LUX_SAVE_INTERVAL` | `60` | Snapshot interval in seconds (0 to disable) |\n| `LUX_SHARDS` | auto | Shard count (default: num_cpus * 16) |\n| `LUX_MAXMEMORY` | `0` (unlimited) | Memory limit (e.g. `100mb`, `1gb`) |\n| `LUX_MAXMEMORY_POLICY` | `noeviction` | Eviction policy: `allkeys-lru`, `volatile-lru`, `allkeys-random`, `volatile-random` |\n| `LUX_MAXMEMORY_SAMPLES` | `5` | Keys sampled per eviction round |\n| `LUX_STORAGE_MODE` | `memory` | Set to `tiered` for hot/cold storage with disk-backed eviction |\n| `LUX_STORAGE_DIR` | `{LUX_DATA_DIR}/storage` | Directory for tiered storage data files |\n| `LUX_RESTRICTED` | (none) | Set to `1` to disable KEYS, FLUSHALL, FLUSHDB |\n\n### Node.js\n\n```bash\nbun i @luxdb/sdk   # or: bun i ioredis\n```\n\n```typescript\nimport { Lux } from \"@luxdb/sdk\"\n\nconst db = new Lux(\"lux://localhost:6379\")\nawait db.set(\"hello\", \"world\")\nawait db.vset(\"doc:1\", [0.1, 0.2, 0.3], { metadata: { title: \"hello\" } })\nconst results = await db.vsearch([0.1, 0.2, 0.3], { k: 5, meta: true })\n```\n\n### Python (redis-py)\n\n```bash\npip install redis\n```\n\n```python\nimport redis\n\nr = redis.Redis(host=\"localhost\", port=6379)\nr.set(\"hello\", \"world\")\nprint(r.get(\"hello\"))  # b\"world\"\n```\n\n### Go (go-redis)\n\n```go\nimport \"github.com/redis/go-redis/v9\"\n\nrdb := redis.NewClient(\u0026redis.Options{Addr: \"localhost:6379\"})\nrdb.Set(ctx, \"hello\", \"world\", 0)\n```\n\n## Testing\n\nLux has 409 tests across unit, integration, property-based, and crash recovery suites.\n\n```bash\ncargo test\n```\n\n| Suite | Tests | What it covers |\n|-------|------:|----------------|\n| **Unit: cmd** | 62 | Every command handler, arg validation, error paths |\n| **Unit: store** | 66 | All data structures, TTL, shard versioning, expiry |\n| **Unit: resp** | 19 | RESP parser, serializers, edge cases |\n| **Unit: snapshot** | 7 | Roundtrip all data types including streams, TTL preservation |\n| **Unit: pubsub** | 5 | Broker subscribe/publish/isolation |\n| **Unit: disk** | 18 | CRC32 checksums, corruption detection, WAL/disk round-trips, partial write recovery, compaction, atomic writes |\n| **Fuzz: persistence** | 7 | proptest-driven: random bytes into parsers (no panics), round-trip equivalence for all 9 data types, WAL replay fidelity, DiskShard reopen consistency |\n| **Integration: transactions** | 29 | MULTI/EXEC, WATCH/UNWATCH, EXECABORT, DISCARD |\n| **Integration: auth** | 6 | Password gating, per-connection state, error paths |\n| **Integration: pubsub** | 10 | Cross-connection message delivery, unsubscribe, sub mode |\n| **Integration: persistence** | 3 | Snapshot save/restart/restore, FLUSHDB+SAVE |\n| **Integration: crash recovery** | 10 | Hard kill + WAL replay for all data types, snapshot+WAL interaction, MULTI/EXEC crash, repeated crash cycles, hot+cold data, DEL/FLUSHDB durability, rapid pipeline crash, corrupted WAL startup |\n| **Integration: tiered** | 18 | Cold storage reads/writes, eviction to disk, WAL crash recovery, snapshot with cold data, compaction |\n| **Integration: pipelines** | 3 | Ordering under contention, fast-path batching |\n| **Integration: blocking** | 6 | BLPOP/BRPOP immediate, timeout, woken-by-push, BLMOVE |\n| **Integration: streams** | 10 | XADD, XREAD, XREADGROUP, XACK, XREAD BLOCK, consumer groups |\n| **Integration: lua** | 10 | EVAL, EVALSHA, redis.call, KEYS/ARGV, SCRIPT LOAD/EXISTS/FLUSH |\n| **Integration: vectors** | 10 | VSET, VGET, VSEARCH, VCARD, metadata filtering, TTL, dimension validation |\n| **Integration: geo** | 14 | GEOADD, GEODIST, GEOPOS, GEOHASH, GEOSEARCH, GEOSEARCHSTORE, GEORADIUS, edge cases |\n| **Integration: hll** | 9 | PFADD, PFCOUNT, PFMERGE, cardinality accuracy, multi-key count, merge, WRONGTYPE |\n| **Integration: timeseries** | 18 | TSADD, TSGET, TSRANGE, TSMRANGE, TSMADD, TSINFO, aggregation, retention, labels, filtering |\n| **Integration: ksub** | 6 | KSUB event delivery, pattern filtering, multiple patterns, KUNSUB, HSET/DEL events |\n| **Integration: http** | 14 | HTTP REST API: health, auth, KV CRUD, tables REST, time series REST, vectors REST, data types, exec, CORS, 404 |\n| **Integration: tables** | 14 | TCREATE, TINSERT, TSELECT, TUPDATE, TDELETE, TDROP, TCOUNT, TLIST, TSCHEMA, joins, foreign keys, unique constraints |\n| **Valkey compat** | 10+ | Valkey multi.tcl test suite run against Lux |\n\nRun the benchmark against Redis:\n\n```bash\n./bench.sh\n```\n\n### CI\n\nEvery push and pull request runs:\n\n- `cargo fmt -- --check`\n- `cargo clippy --all-targets -- -D warnings`\n- `cargo test --all-targets`\n- Integration tests against the Valkey test harness\n\nRelease and Docker builds only proceed after tests pass.\n\n## Supported Commands\n\n**Strings:** `SET` `GET` `SETNX` `SETEX` `PSETEX` `GETSET` `GETDEL` `GETEX` `GETRANGE` `SETRANGE` `MGET` `MSET` `MSETNX` `STRLEN` `APPEND` `INCR` `DECR` `INCRBY` `DECRBY` `INCRBYFLOAT` `SETBIT` `GETBIT` `BITCOUNT` `BITPOS` `BITOP`\n\n**Keys:** `DEL` `UNLINK` `EXISTS` `KEYS` `SCAN` `TYPE` `RENAME` `RENAMENX` `RANDOMKEY` `COPY` `TTL` `PTTL` `EXPIRE` `PEXPIRE` `EXPIREAT` `PEXPIREAT` `EXPIRETIME` `PEXPIRETIME` `PERSIST` `DBSIZE` `FLUSHDB` `FLUSHALL`\n\n**Lists:** `LPUSH` `RPUSH` `LPUSHX` `RPUSHX` `LPOP` `RPOP` `BLPOP` `BRPOP` `BLMOVE` `LLEN` `LRANGE` `LINDEX` `LSET` `LINSERT` `LREM` `LTRIM` `LPOS` `LMOVE` `RPOPLPUSH`\n\n**Hashes:** `HSET` `HSETNX` `HMSET` `HGET` `HMGET` `HDEL` `HGETALL` `HKEYS` `HVALS` `HLEN` `HEXISTS` `HINCRBY` `HINCRBYFLOAT` `HSTRLEN` `HRANDFIELD` `HSCAN`\n\n**Sets:** `SADD` `SREM` `SMEMBERS` `SISMEMBER` `SMISMEMBER` `SCARD` `SPOP` `SRANDMEMBER` `SMOVE` `SUNION` `SINTER` `SDIFF` `SUNIONSTORE` `SINTERSTORE` `SDIFFSTORE` `SINTERCARD` `SSCAN`\n\n**Sorted Sets:** `ZADD` `ZSCORE` `ZMSCORE` `ZRANK` `ZREVRANK` `ZREM` `ZCARD` `ZCOUNT` `ZLEXCOUNT` `ZINCRBY` `ZRANGE` `ZREVRANGE` `ZRANGEBYSCORE` `ZREVRANGEBYSCORE` `ZRANGEBYLEX` `ZREVRANGEBYLEX` `ZPOPMIN` `ZPOPMAX` `BZPOPMIN` `BZPOPMAX` `ZUNIONSTORE` `ZINTERSTORE` `ZDIFFSTORE` `ZREMRANGEBYRANK` `ZREMRANGEBYSCORE` `ZREMRANGEBYLEX` `ZSCAN`\n\n**Geo:** `GEOADD` `GEODIST` `GEOPOS` `GEOHASH` `GEOSEARCH` `GEOSEARCHSTORE` `GEORADIUS` `GEORADIUSBYMEMBER` `GEORADIUS_RO` `GEORADIUSBYMEMBER_RO`\n\n**Streams:** `XADD` `XLEN` `XRANGE` `XREVRANGE` `XREAD` `XREADGROUP` `XGROUP CREATE` `XGROUP DESTROY` `XACK` `XPENDING` `XCLAIM` `XAUTOCLAIM` `XDEL` `XTRIM` `XINFO STREAM` `XINFO GROUPS`\n\n**HyperLogLog:** `PFADD` `PFCOUNT` `PFMERGE`\n\n**Time Series:** `TSADD` `TSMADD` `TSGET` `TSRANGE` `TSMRANGE` `TSINFO`\n\n**Pub/Sub:** `PUBLISH` `SUBSCRIBE` `PSUBSCRIBE` `UNSUBSCRIBE` `PUNSUBSCRIBE` `KSUB` `KUNSUB`\n\n**Transactions:** `MULTI` `EXEC` `DISCARD` `WATCH` `UNWATCH`\n\n**Vectors:** `VSET` `VGET` `VSEARCH` `VCARD`\n\n**Tables:** `TCREATE` `TINSERT` `TSELECT` `TUPDATE` `TDELETE` `TDROP` `TCOUNT` `TSCHEMA` `TLIST` `TALTER`\n\n**Scripting:** `EVAL` `EVALSHA` `SCRIPT LOAD` `SCRIPT EXISTS` `SCRIPT FLUSH`\n\n**Sorting:** `SORT` `SORT_RO`\n\n**Server:** `PING` `ECHO` `QUIT` `HELLO` `INFO` `TIME` `SAVE` `BGSAVE` `LASTSAVE` `AUTH` `CONFIG` `CLIENT` `SELECT` `COMMAND` `OBJECT` `MEMORY`\n\n## Known Differences from Redis\n\nLux is Redis-compatible but not identical. Key differences:\n\n- **No AOF persistence** -- Lux uses snapshots + a write-ahead log (WAL) with CRC32 checksums instead of Redis AOF. The WAL is fsync'd every 1 second (matching Redis `appendfsync everysec`). Maximum data loss on power failure is 1 second of writes\n- **No RESP3 protocol** -- RESP2 only\n- **No cluster mode** -- single-node only (use Lux Cloud for managed hosting)\n- **MULTI/EXEC** -- supported with WATCH-based optimistic locking. Commands in a transaction execute sequentially, each acquiring its own shard lock, so another client could observe intermediate state mid-EXEC. Redis avoids this via single-threading. Standard client libraries (Redlock, BullMQ, Sidekiq) rely on WATCH for correctness, not EXEC isolation. Full shard-locking isolation may be added in a future release if there's demand\n- **Pipeline ordering** -- per-client command order is preserved. Consecutive same-shard commands are batched for performance\n\n## Architecture\n\n```\nClient connections (tokio tasks)\n        |\n   Zero-Copy RESP Parser (byte slices, no allocations)\n        |\n   Pipeline Batching (consecutive same-shard commands batched)\n        |\n   Command Dispatch (byte-level matching, no string conversion)\n        |\n   Sharded Store (auto-tuned RwLock shards, hashbrown raw_entry)\n        |\n   FNV Hash -\u003e Shard Selection (pre-computed, reused for HashMap lookup)\n```\n\nRead the full deep dive at [luxdb.dev/architecture](https://luxdb.dev/architecture).\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flux-db%2Flux","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flux-db%2Flux","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flux-db%2Flux/lists"}