Redis

Lightweight in-memory Redis implementation speaking the real RESP protocol.

KeyValue
Port6379
ProtocolRESP (TCP)
Size~50 KB
Startup< 500ms

Default Connection

redis://parlel-bridge:6379

(Use localhost instead of parlel-bridge if you run the bridge outside Docker and publish its ports.)

No auth required. All commands accepted. AUTH is accepted as a no-op (the dev pool does not enforce credentials).

Replies are framed in the real RESP protocol: nested arrays (SCAN, SSCAN/HSCAN/ZSCAN, MGET, HMGET, GEOPOS, XRANGE) are encoded as RESP arrays, missing entries come back as nil bulk ($-1), and typed errors use the real error code (-WRONGTYPE …, -ERR value is not an integer or out of range, -ERR no such key, -ERR unknown command …), so ioredis, node-redis, and redis-py parse them unmodified.

Supported Commands

Connection

CommandNotes
PINGReturns PONG
ECHOReturns the message
AUTHAccepted (no-op)
SELECTAccepted (single DB)
QUITCloses connection

Strings

CommandNotes
SET key value [EX seconds]Set with optional expiry
GET keyGet value
DEL key [key ...]Delete keys
UNLINK key [key ...]Async delete (same as DEL)
EXISTS key [key ...]Check existence
EXPIRE key secondsSet TTL in seconds
EXPIREAT key timestampSet expiry as Unix timestamp
PEXPIRE key msSet TTL in milliseconds
PEXPIREAT key ms-timestampSet expiry as ms timestamp
TTL keyGet remaining TTL (seconds)
PTTL keyGet remaining TTL (ms)
PERSIST keyRemove expiry
TYPE keyReturns type of value
RENAME key newkeyRename a key
RENAMENX key newkeyRename only if newkey doesn't exist
APPEND key valueAppend to string
STRLEN keyGet string length
GETRANGE key start endGet substring
SETRANGE key offset valueOverwrite substring
GETSET key valueSet and return old value
GETDEL keyGet and delete
SETNX key valueSet only if not exists
MSET key value [key value ...]Set multiple
MGET key [key ...]Get multiple
MSETNX key value [key value ...]Set multiple if none exist
COPY src dstCopy a key

Counters

CommandNotes
INCR keyIncrement by 1
DECR keyDecrement by 1
INCRBY key amountIncrement by amount
DECRBY key amountDecrement by amount
INCRBYFLOAT key amountIncrement by float

Lists

CommandNotes
LPUSH key value [value ...]Push to head
RPUSH key value [value ...]Push to tail
LPOP keyPop from head
RPOP keyPop from tail
LLEN keyGet length
LINDEX key indexGet by index
LSET key index valueSet by index
LRANGE key start stopGet range
LREM key count valueRemove elements
LINSERT key BEFORE|AFTER pivot valueInsert relative to pivot
LPOS key valueFind position
LMOVE src dst srcpos dstposMove element between lists

Sets

CommandNotes
SADD key member [member ...]Add members
SREM key member [member ...]Remove members
SMEMBERS keyGet all members
SISMEMBER key memberCheck membership
SCARD keyGet cardinality
SPOP keyRemove and return random member
SRANDMEMBER key [count]Get random members
SDIFF key [key ...]Difference
SINTER key [key ...]Intersection
SUNION key [key ...]Union
SORT keySort elements

Hashes

CommandNotes
HSET key field value [field value ...]Set fields
HSETNX key field valueSet field if not exists
HGET key fieldGet field
HMGET key field [field ...]Get multiple fields
HMSET key field value [field value ...]Set multiple fields
HGETALL keyGet all fields and values
HDEL key field [field ...]Delete fields
HEXISTS key fieldCheck field existence
HKEYS keyGet all field names
HVALS keyGet all values
HLEN keyGet number of fields
HINCRBY key field amountIncrement field by integer
HINCRBYFLOAT key field amountIncrement field by float

Sorted Sets

CommandNotes
ZADD key score member [score member ...]Add with scores
ZREM key member [member ...]Remove members
ZRANGE key start stopGet range by index
ZREVRANGE key start stopReverse range
ZRANGEBYSCORE key min maxRange by score
ZRANK key memberGet rank
ZREVRANK key memberGet reverse rank
ZSCORE key memberGet score
ZCARD keyGet cardinality
ZINCRBY key amount memberIncrement score

HyperLogLog

CommandNotes
PFADD key element [element ...]Add elements
PFCOUNT key [key ...]Get approximate count
PFMERGE dest source [source ...]Merge sketches

Streams

CommandNotes
XADD key ID field valueAppend to stream
XLEN keyGet stream length
XRANGE key start stopRead range
XREVRANGE key stop startReverse range
XREAD COUNT count STREAMS key IDRead from streams
XDEL key ID [ID ...]Delete entries

Geo

CommandNotes
GEOADD key longitude latitude memberAdd geo entry
GEODIST key member1 member2Distance between members
GEOPOS key memberGet position
GEORADIUS key longitude latitude radiusSearch by radius

Pub/Sub

CommandNotes
SUBSCRIBE channel [channel ...]Subscribe to channels
UNSUBSCRIBE [channel ...]Unsubscribe
PUBLISH channel messagePublish message

Transactions

CommandNotes
MULTIStart transaction
EXECExecute transaction
DISCARDDiscard transaction
WATCH key [key ...]Watch keys for changes
UNWATCHUnwatch all keys

Server

CommandNotes
DBSIZENumber of keys
FLUSHDBClear current database
FLUSHALLClear all databases
KEYS patternFind keys by pattern
SCAN cursor [MATCH pattern]Incremental key scan
RANDOMKEYReturn a random key
INFOServer information
TIMEServer time
SAVESynchronous save
BGSAVEBackground save
BGREWRITEAOFRewrite AOF
LASTSAVELast save timestamp
SHUTDOWNStop server
DEBUGDebug commands
MEMORYMemory diagnostics
LATENCYLatency diagnostics
SLOWLOGSlow query log
ACLAccess control
CLIENTClient commands
CLUSTERCluster commands
COMMANDCommand info
CONFIGConfiguration
SWAPDBSwap databases
WAITWait for replication
OBJECTKey internals
MIGRATEMigrate keys
RESTORERestore key
DUMPSerialize key
MODULELoad modules
REPLICAOFSet replication
SLAVEOFSet replication (legacy)
MONITORStream commands
BITCOUNTCount set bits
BITOPBitwise operations
BITPOSFind first bit
GETBITGet bit
SETBITSet bit
SETRANGESet range
EVALLua scripting
EVALSHALua by SHA
SORTSort list/set/sorted set
PFADDHyperLogLog add
PFCOUNTHyperLogLog count
PFMERGEHyperLogLog merge

Surface coverage

Legend: ✅ supported · ◐ accepted-not-enforced · ✓ by design · ⟳ roadmap

AreaStatusNotes
RESP framing (nested arrays, nil bulk, integer replies)SCAN/SSCAN/HSCAN/ZSCAN return [cursor, [items]]; MGET/HMGET return nil for misses
Strings: SET GET APPEND STRLEN GETRANGE SETRANGE GETSET GETDEL SETNX MSET MGET MSETNXexercised over the wire
Counters: INCR DECR INCRBY DECRBYnon-integer values return -ERR value is not an integer or out of range
INCRBYFLOATreturns bulk string; no overflow checks
Keys: DEL UNLINK EXISTS EXPIRE/PEXPIRE/EXPIREAT/PEXPIREAT TTL/PTTL PERSIST TYPE RENAME RENAMENX KEYS SCAN RANDOMKEY COPYTTL returns -2 (missing) / -1 (no expiry)
KEYS globsupports * prefix/suffix/contains, not full glob ([a-z], ?)
Lists: LPUSH RPUSH LPOP RPOP LLEN LINDEX LSET LRANGE LREM LINSERT LPOS LMOVELSET/RENAME on missing key return -ERR no such key
BLPOP/BRPOPnon-blocking — pop if available, else nil (no wait)
Sets: SADD SREM SMEMBERS SISMEMBER SCARD SUNION SINTER SDIFF SPOP SRANDMEMBER SSCAN SORT
Hashes: HSET HSETNX HGET HMGET HMSET HGETALL HDEL HEXISTS HKEYS HVALS HLEN HINCRBY HINCRBYFLOAT HSCANHSET returns the count of genuinely new fields
Sorted sets: ZADD ZREM ZRANGE ZREVRANGE ZRANGEBYSCORE ZRANK ZREVRANK ZSCORE ZCARD ZINCRBY ZSCANbase path
ZADD flags (NX/XX/GT/LT/CH/INCR)not parsed
Pub/Sub: SUBSCRIBE UNSUBSCRIBE PUBLISHmessages are delivered to subscribers; single + multi channel; no PSUBSCRIBE/pattern matching
Transactions: MULTI EXEC DISCARD WATCH UNWATCHaccepted; commands are not queued/isolated
Bitmaps: SETBIT GETBIT BITCOUNT BITPOS BITOPBITOP/BITPOS simplified
HyperLogLog: PFADD PFCOUNT PFMERGEexact-set approximation (not probabilistic)
Streams: XADD XLEN XRANGE XREVRANGE XREAD XDELsimplified IDs (not strictly monotonic per ms)
Geo: GEOADD GEOPOS GEODIST GEORADIUSEuclidean approximation, not haversine
Scripting: EVAL EVALSHAaccepted, return nil (no Lua VM by design)
Auth / ACL credential enforcementaccepted, not enforced (ephemeral in-memory dev pool)
Persistence (SAVE/BGSAVE/AOF)no-op — state is ephemeral by design
Clustering / replicationsingle-node by design

Error codes & shapes

RESP errors carry the real error code as the first token, so client libraries that branch on it behave the same as against production Redis:

ScenarioReply
Type mismatch (e.g. GET on a list)-WRONGTYPE Operation against a key holding the wrong kind of value
INCR/DECR/INCRBY/DECRBY on a non-integer value-ERR value is not an integer or out of range
LSET/RENAME/RENAMENX on a missing key-ERR no such key
Unknown command-ERR unknown command '<NAME>'
Wrong argument count-ERR wrong number of arguments for '<CMD>' command
Missing key (read)nil bulk ($-1) — e.g. GET, HGET, LPOP, ZSCORE

Usage

Add the parlel/bridge sidecar to your test compose file. Your app connects to the plain parlel-bridge hostname with unmodified real drivers — no Parlel code in your app.

include:
  - path: parlel-bridge.yml          # image: parlel/bridge
services:
  app:
    build: .
    env_file: test.env
    depends_on:
      parlel-bridge: { condition: service_healthy }

Run it:

PARLEL_API_KEY=pk_... docker compose -f docker-compose.test.yml up

Then connect with your normal client. Python:

import redis

r = redis.Redis(host="parlel-bridge", port=6379)
r.set("user:1", "alice")
print(r.get("user:1"))
r.incr("counter")
r.expire("counter", 3600)

Node:

import Redis from "ioredis";

const redis = new Redis({ host: "parlel-bridge", port: 6379 });
await redis.set("key", "value");
await redis.get("key");

Via MCP (Parlel Sandbox)

When Redis runs inside a Parlel sandbox, drive it through the sandbox's MCP endpoint with parlel_execute. Pass a raw Redis command string as command:

{
  "jsonrpc": "2.0", "id": 1, "method": "tools/call",
  "params": {
    "name": "parlel_execute",
    "arguments": { "service": "redis", "command": "SET hello world" }
  }
}

The decoded RESP reply is returned as { reply: ... }.

Seed Data

# cache-seed.txt
SET user:1 '{"id":1,"name":"Alice","email":"alice@test.com"}'
SET user:2 '{"id":2,"name":"Bob","email":"bob@test.com"}'
SET session:abc '{"userId":1,"role":"admin"}'
EXPIRE session:abc 3600
SET config:theme "dark"
SET config:lang "en"

Seed via MCP parlel_execute, or run these against the bridge with your normal client.

Access via Parlel Sandbox

The parlel/bridge sidecar (image: parlel/bridge) exposes Redis on parlel-bridge:6379. It tunnels the raw RESP protocol as TCP over the sandbox's HTTPS preview proxy via WebSocket, so redis-py, ioredis, or any client connects to redis://parlel-bridge:6379 unmodified — with just an API key. No SSH tunnel, no daytona CLI. (Use localhost instead of parlel-bridge if you run the bridge outside Docker and publish its ports.) Postgres and Redis start by default in a new sandbox.