Documentation for agents: an index at /llms.txt, every docs page in one file at /llms-full.txt, and Markdown for any docs page by adding .md to its URL.

Effect KitRedis

RESP2 and RESP3

Look up how the client negotiates the Redis protocol, how it falls back, and how replies are normalized.

The client speaks the Redis wire protocol itself. It can use RESP3 or RESP2, and the commands, option types and reply types are the same under both. The protocol option chooses what the connection asks for.

The protocol option

ValueBehavior
"auto"Send HELLO 3. If the server answers that it does not know HELLO or the protocol version, continue on RESP2. Any other rejection fails the connection. This is the default.
"resp3"Send HELLO 3. Any rejection fails the connection. There is no fallback.
"resp2"Do not send HELLO. The connection stays on RESP2.

Example (Pinning a Protocol)

import {  } from "@effect-kit/redis/node";

export const  = .({ : "redis://localhost:6379", : "resp2" });

HELLO 3 is sent after authentication and before CLIENT SETNAME and SELECT. The fallback in auto applies only to two rejections: NOPROTO unsupported protocol version and ERR unknown command 'HELLO'. A connection that is rejected for another reason fails with a HandshakeError with stage: "hello". If the server accepts HELLO 3 but does not report protocol 3, the connection also fails with stage: "hello".

The negotiated protocol is ConnectionSnapshot.protocol, which is "resp2", "resp3" or undefined before the handshake completes. Upstash HTTP has no protocol option.

What changes between the two

Nothing in the API. The reply decoders accept both shapes and return one type:

  • Members (smembers, sinter) decode from a RESP3 set or a RESP2 array into readonly Uint8Array[].
  • Field and value pairs (hgetall) decode from a RESP3 map, a RESP2 flat array or an array of pairs into an ordered array of tuples. Binary keys and duplicate keys are kept, and nothing becomes a JavaScript object.
  • Scores decode from a RESP3 double or a RESP2 bulk string into the server's decimal text, or a number for zscore.
  • A missing value is None. RESP2 uses a nil bulk string or a nil array and RESP3 uses a null. A nil array is not a missing scalar: an empty pop such as lpopCount on a missing list is None, and a missing string is None too, each through its own decoder.
  • Attribute replies are unwrapped before decoding.

RespValue

Replies are decoded into a lossless RespValue first and then into a typed value. redis.raw returns the RespValue without decoding it. Error replies from raw arrive as values of _tag: "SimpleError" or "BlobError" and do not fail the Effect.

_tagFieldsProtocol
SimpleStringvalue: Uint8ArrayRESP2, RESP3
BlobStringvalue: Uint8ArrayRESP2, RESP3
SimpleErrorvalue: Uint8ArrayRESP2, RESP3
BlobErrorvalue: Uint8ArrayRESP3
Integervalue: bigintRESP2, RESP3
BigNumbervalue: bigintRESP3
Doublevalue: stringRESP3
Booleanvalue: booleanRESP3
Nullkind: "resp3" | "bulk" | "array"RESP2 (bulk, array), RESP3 (resp3)
VerbatimStringformat: Uint8Array, value: Uint8ArrayRESP3
Arrayvalues: ReadonlyArray<RespValue>RESP2, RESP3
Mapentries: RespPairsRESP3
Setvalues: ReadonlyArray<RespValue>RESP3
Pushvalues: ReadonlyArray<RespValue>RESP3
Attributeentries: RespPairs, value: RespValueRESP3

RespPairs is ReadonlyArray<readonly [RespValue, RespValue]>. Doubles stay as text so no precision is lost.

Example (Inspecting a Raw Reply)

import {  } from "effect";

import {  } from "@effect-kit/redis";
import type { RawContract } from "@effect-kit/redis";

const : RawContract = { : "ordinary", : { : "Keyless" } };

const  = .(function* () {
  const  = yield* ;

  const reply = yield* .(["ECHO", "hello"], );
const reply: RespValue
return .; });

Low-level codec

encodeCommand(tokens, limits?) returns a Result with the RESP frame or a ProtocolError. makeRespDecoder(limits?) returns a Result with a RespDecoder that you feed bytes, drain with next, and close with end. The decode limits are maxHeaderBytes, maxBlobBytes, maxBufferedBytes, maxAggregateEntries and maxNestingDepth, set through limits. A frame that breaks the grammar or a limit fails with a ProtocolError.

Replication and RDB framing and streamed RESP3 aggregates are outside the ordinary command API.