Step 1 of 3 · Reading · ~2 min
RESP Wire Format
RESP Protocol Fundamentals
The RESP Wire Format
You've used two RESP types so far (simple strings and bulk strings) without naming the whole system. This lesson fills in the rest of the alphabet you'll need for the entire course: errors, integers, and null.
The five basic RESP types
| Prefix | Type | Format | Example |
|---|---|---|---|
+ | Simple String | +<text>\r\n | +OK\r\n |
- | Error | -<text>\r\n | -ERR unknown command 'FOO'\r\n |
: | Integer | :<number>\r\n | :42\r\n |
$ | Bulk String | $<len>\r\n<data>\r\n | $3\r\nfoo\r\n |
$ | Null Bulk String | $-1\r\n | $-1\r\n |
Every reply your server ever sends — no matter how complex the command — boils down to one of these (plus arrays, which you'll add when you build a real command parser). The prefix byte is what lets a client tell, before parsing anything else, whether it received a string, a number, an error, or nothing at all.
Why errors are a distinct type, not a magic string
If errors were just bulk strings, clients would have to guess whether "ERR wrong type" was a real value or a failure. By giving errors their own - prefix, a client can do:
Errors also follow a loose convention: an uppercase error code word, then a human-readable message — ERR, WRONGTYPE, NOAUTH, etc. You'll only need ERR for now.
Why null needs its own encoding
$-1\r\n is not "a bulk string of length -1" in any literal sense — it's a sentinel meaning "no value," distinct from an empty string ($0\r\n\r\n). This distinction matters immediately: GET on a missing key must return null, not an empty string, or client libraries will treat "key not found" the same as "key holds an empty string," which is wrong.
Building a serializer, not string formatting scattered everywhere
Now is the moment to consolidate every reply-building call site behind small serializer functions:
Adding COMMAND DOCS and unknown-command handling
COMMAND DOCS is a real Redis introspection command that clients (and testing tools) sometimes call to check server capability; for now you just need it to reply +OK\r\n so nothing breaks. More importantly, add a catch-all branch in your dispatcher:
This is the pattern every future command addition will follow: write the handler, register it in the table, and let the fallback handle everything you haven't implemented yet.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…