Skip to content

Overview & Differences

FrogDB implements RESP2 and RESP3 and targets compatibility with the Redis 8.6.0 command set. Standard Redis client libraries connect without modification. This page documents only the behavioral differences; for standard Redis behavior, see the Redis documentation. For the exact per-command support status, see the Command matrix; for the regression evidence behind the compatibility claim, see Test suite results and Testing methodology.

FrogDB advertises redis_version:{versions.advertised_redis_version} in INFO and to the Lua REDIS_VERSION binding, so client libraries that feature-detect on the reported version behave as they would against that Redis release. The compatibility target — the command set and regression suite FrogDB is measured against — is Redis 8.6.0.

RedisFrogDB
Command processingSingle-threaded (separate I/O threads for socket reads/writes)Shared-nothing, sharded worker threads
Storage engineIn-memory with RDB/AOF filesIn-memory with a RocksDB write-ahead log and SST files
Cluster coordinationGossip protocolRaft consensus with an orchestrated control plane
Configuration formatredis.conffrogdb.toml (TOML)
Allocatorjemallocjemalloc
Lua version5.15.4

FrogDB persists data through RocksDB rather than Redis RDB snapshots and AOF logs:

  • No RDB or AOF files. Data lives in RocksDB SST files fronted by a write-ahead log.
  • Forkless BGSAVE. BGSAVE triggers a snapshot without a fork() of the server process.
  • No BGREWRITEAOF. RocksDB manages WAL rotation and compaction internally.
  • Durability modes are async, periodic, and sync (persistence.durability-mode), replacing Redis appendfsync always/everysec/no. In sync mode the server waits for an fsync before acknowledging a write.
  • Redis RDB files cannot be imported. The on-disk formats are unrelated.

See Persistence & durability for configuration and recovery details.

FrogDB is configured with a TOML file instead of redis.conf. Common mappings:

redis.conffrogdb.toml
bind 0.0.0.0server.bind = "0.0.0.0"
port 6379server.port = 6379
requirepass secretsecurity.requirepass = "secret"
maxmemory 1gbmemory.maxmemory = "1gb"
maxclients 10000server.max-clients = 10000
appendonly yespersistence.enabled = true
appendfsync everysecpersistence.durability-mode = "periodic"
save 900 1snapshot.snapshot-interval-secs = 900

Environment variables use the FROGDB_ prefix with double underscores for nesting, e.g. FROGDB_SERVER__PORT=6380. Runtime changes made with CONFIG SET can be written back to the TOML file with CONFIG REWRITE, which merges the current runtime values into the existing document and preserves its comments.

See Configuration for the four configuration surfaces and precedence, and the Configuration reference for every parameter.

FrogDB coordinates cluster membership with Raft consensus rather than Redis Cluster’s gossip protocol:

  • Orchestrated control plane. There is no CLUSTER MEET; topology is managed through the admin API.
  • Deterministic failover. Raft leader election replaces gossip-based failover.
  • Two-level sharding. The 16384 cluster hash slots are mapped onto internal shard workers.
  • CLUSTER BUMPEPOCH is not supported.
  • Replica migration is manual rather than automatic.

See Clustering for bootstrap steps, the admin API, and failure modes.

FrogDB partitions keys across internal shards even in standalone mode, so multi-key operations are subject to slot rules that plain single-node Redis does not enforce.

In cluster mode, multi-key commands (MGET, MSET, and similar) require all keys to hash to the same slot, or they return -CROSSSLOT. In standalone mode, cross-slot multi-key operations also return -CROSSSLOT by default. Set server.allow-cross-slot-standalone = true to allow them via scatter-gather; note that MSETNX always requires same-slot keys.

  • MULTI/EXEC requires all keys in the same hash slot in cluster mode.
  • In standalone mode, cross-shard transactions obtain atomicity through VLL.
  • WATCH uses per-key version tracking.
  • Blocking list and stream commands (BLPOP, BRPOP, BLMOVE, and similar) require their keys on the same shard.
  • A cross-shard blocking call returns -CROSSSLOT. This holds even in standalone mode with server.allow-cross-slot-standalone = true: the escape hatch does not extend to blocking commands, because a blocking wait must be registered on a single shard that owns all the watched keys.

FrogDB runs scripts on an embedded Lua 5.4 interpreter (Redis uses Lua 5.1), which introduces a few edge-case syntax and semantic differences at the language level. The FrogDB-specific behavioral differences are:

Every key a script accesses must be declared through KEYS[]. Accessing an undeclared key returns an error (script tried to access undeclared key). Redis permits undeclared key access but documents it as unsupported.

-- Works: the key is declared
EVAL "return redis.call('GET', KEYS[1])" 1 mykey
-- Errors in FrogDB (accepted by Redis): 'mykey' is not declared
EVAL "return redis.call('GET', 'mykey')" 0

By default, all keys accessed by a script must hash to the same shard; a script spanning multiple shards returns a CROSSSLOT error. As with multi-key commands, setting server.allow-cross-slot-standalone = true permits cross-shard scripts.

  • redis.setresp() is not supported and returns an error.

In standalone mode, PUBLISH/SUBSCRIBE and pattern subscriptions (PSUBSCRIBE) behave identically to Redis.

In cluster mode:

  • Regular Pub/Sub messages are forwarded across cluster nodes, so a subscriber on any node receives them — matching Redis behavior.
  • Sharded Pub/Sub (SSUBSCRIBE/SPUBLISH) routes messages to the shard that owns the channel’s hash slot, consistent with Redis Cluster.

Unlike Redis, FrogDB enforces a per-client subscription cap, configurable via blocking.max-subscriptions-per-client (Redis has no built-in per-client limit).

FrogDB exposes a single logical database (db0). SELECT 0 is a no-op; SELECT with a non-zero index returns an error. MOVE and SWAPDB are not supported.

The following commands and features are intentionally absent because they do not fit FrogDB’s architecture. The Command matrix is the exhaustive per-command view.

Command / featureReason
SELECT (non-zero index)Single-database model
MOVE, SWAPDBSingle-database model
MODULE *No loadable-module architecture
BGREWRITEAOFNo AOF; RocksDB manages WAL lifecycle
SYNCLegacy full-sync; superseded by PSYNC
CLUSTER BUMPEPOCHRaft manages epochs, not manual bumping
DEBUG SEGFAULT / RELOAD / CRASH-AND-RECOVERUnsafe debug subcommands are disabled
redis.setresp() in LuaNot implemented
ACL selectors v2 ((...), clearselectors)Not supported; use separate users instead
Diskless replicationNot applicable; FrogDB does not replicate via RDB transfer

FrogDB offers a two-tier hot/warm store as an alternative to eviction. With the tiered-lru or tiered-lfu eviction policy, instead of deleting a key under memory pressure FrogDB serializes its value to the RocksDB warm tier (a spill); the key’s metadata stays in memory and reads transparently deserialize the value back (an unspill).

Tiered storage requires persistence to be enabled. Open-source Redis has no equivalent — it only evicts (deletes) keys when memory is full. See the Configuration reference for the tiered-storage settings.