APPEND and String Length
The APPEND command adds data onto the end of an existing Redis string without you having to read the current value back into your application, concatenate it, and write it out again. STRLEN tells you how many bytes a string currently holds, in O(1) time, without transferring the value itself. Together they make Redis strings useful as growing buffers — log lines, message bodies, streamed chunks — while letting you check size cheaply before deciding whether to trim, rotate, or read the whole thing.
Overview / How It Works
A Redis string is a binary-safe sequence of bytes, up to 512MB, internally represented as a structure called an SDS (Simple Dynamic String) rather than a plain C string. An SDS stores its length explicitly and keeps some spare, pre-allocated capacity at the end of its buffer. This matters directly for APPEND: when you append data, Redis does not necessarily reallocate the whole buffer every time. If there is spare capacity left over from a previous allocation, Redis just writes the new bytes into that space and updates the stored length — an O(1) operation. When the buffer does need to grow, Redis over-allocates (doubling the buffer up to 1MB, then growing by fixed 1MB chunks past that point) so that the *next* several appends are cheap again. This is why APPEND is described as O(1) amortized: any single call could trigger a reallocation and a memory copy, but averaged over many calls the cost per append stays constant.
STRLEN simply reads the length field already stored in the SDS header — it never scans the bytes of the string — so it is O(1) regardless of how large the value is.
A key behavior to internalize: if you call APPEND on a key that does not exist yet, Redis treats it as if the key held an empty string and creates it fresh with the appended value as its full content. There is no error, and no need to initialize the key with SET first. Conversely, calling STRLEN on a key that does not exist returns (integer) 0, not an error and not (nil) — an absent key behaves like a zero-length string for sizing purposes.
Because every key in Redis has exactly one type, APPEND and STRLEN only work on keys that hold a string (or don’t exist yet). Calling either on a key holding a list, hash, set, or sorted set returns a WRONGTYPE error and does not modify anything.
One subtlety that trips people up: APPEND does not clear an existing TTL. This is different from a plain SET, which wipes out any TTL on the key unless you add the KEEPTTL option. Because APPEND is a targeted mutation rather than a full overwrite, Redis leaves the key’s expiration exactly as it was.
Syntax
APPEND key value
STRLEN key
| Argument | Meaning |
|---|---|
key |
The name of the string key to read or modify. Created automatically by APPEND if it does not exist. |
value |
(APPEND only) The bytes to add onto the end of the current value. Redis treats this as raw binary data, not text with any particular encoding. |
| Command | Return value | Time complexity |
|---|---|---|
APPEND key value |
Integer: length of the string after the append | O(1) amortized |
STRLEN key |
Integer: length of the string, or 0 if the key doesn’t exist |
O(1) |
Examples
Example 1: Basic append and length check
SET greeting "Hello"
APPEND greeting " World"
GET greeting
STRLEN greeting
Output:
OK
(integer) 11
"Hello World"
(integer) 11
SET creates the key with the value Hello (5 bytes). APPEND adds " World" (6 bytes, including the leading space) and returns 11, the total length after the append — not just the length of what was added. GET confirms the final value, and STRLEN confirms the byte count matches what APPEND already told us.
Example 2: APPEND on a key that doesn’t exist yet
STRLEN counter:missing
APPEND counter:missing "5"
STRLEN counter:missing
APPEND counter:missing "5"
GET counter:missing
Output:
(integer) 0
(integer) 1
(integer) 1
(integer) 2
"55"
STRLEN on the nonexistent key returns 0 instead of an error. The first APPEND silently creates counter:missing with the value "5". The second APPEND does not add 5 to 5 — it concatenates the bytes, producing the two-character string "55". This is a deliberate illustration of a pitfall covered below: APPEND is a byte-concatenation operation, never arithmetic.
Example 3: APPEND preserves TTL; SET does not
SET session:abc123 "user=42" EX 60
TTL session:abc123
APPEND session:abc123 ";status=active"
GET session:abc123
TTL session:abc123
Output:
OK
(integer) 60
(integer) 21
"user=42;status=active"
(integer) 60
(In practice the final TTL may read a second or two lower than 60 depending on how much time passed while typing the commands — the point is that it is still a positive, decreasing number, not reset or wiped out.) The session key was created with a 60-second expiration. Appending more data onto it does not touch that expiration at all, because APPEND mutates the existing value in place rather than replacing it the way SET does.
How It Works Step by Step
When Redis receives APPEND key value, it performs roughly this sequence, all as a single atomic step on the main thread (Redis is single-threaded for command execution, so nothing else can interleave partway through):
- Look up
key. If it doesn’t exist, create it as an empty SDS string first. - If the key exists but holds a non-string type, stop immediately and return a
WRONGTYPEerror — nothing is modified. - Check whether the existing SDS buffer has enough free capacity at the end to hold the new bytes.
- If there’s enough spare capacity, copy the new bytes directly into place and update the stored length — no reallocation needed.
- If there isn’t enough capacity, allocate a larger buffer (following the doubling/1MB-chunk growth strategy), copy the old bytes plus the new bytes into it, and update the key’s pointer to the new buffer.
- Return the new total length as an integer reply.
STRLEN key is much simpler: look up the key, and if it holds a string, read the length field that the SDS structure already maintains and return it — no scanning, no copying.
Common Mistakes
Mistake 1: Using APPEND to build a counter. As shown in Example 2, appending digit strings concatenates them as text rather than adding them numerically.
SET visits "5"
APPEND visits "5"
GET visits
Output:
OK
(integer) 2
"55"
If the goal is a numeric counter, use INCR or INCRBY instead, which parse the string as an integer and increment it atomically:
SET visits "5"
INCR visits
GET visits
Output:
OK
(integer) 6
"6"
Mistake 2: Calling APPEND (or STRLEN) on a key that holds the wrong type. Every Redis key has exactly one data type, so mixing command families on the same key fails.
LPUSH mylist:1 "a"
APPEND mylist:1 "b"
Output:
(integer) 1
(error) WRONGTYPE Operation against a key holding the wrong kind of value
mylist:1 is a list, so APPEND refuses to run. The fix is simply to use the right key or the right command family — list values are grown with RPUSH/LPUSH, not APPEND.
Mistake 3: Assuming a typo’d key name will error out. Because APPEND silently creates missing keys, a typo like APPEND ssession:abc123 "..." won’t fail — it just quietly creates a new, permanent, forgotten key. Always double-check key names, and consider scanning for unexpected keys (with SCAN, never KEYS on a large dataset, since KEYS is O(N) and blocks the single-threaded server for the entire scan) if you suspect this has happened.
Mistake 4: Forgetting a TTL entirely on a growing buffer. A key that only ever receives APPEND calls and is never given an EXPIRE will grow and persist forever, since APPEND does nothing to set or clear expiration. If the buffer is meant to be temporary (a session log, a request trace), set a TTL explicitly with EXPIRE when you first create the key.
Best Practices
- Use
APPENDfor building up byte buffers (log lines, streamed fragments, message bodies) — never for anything that should be treated as a number. - Check size with
STRLENbefore appending more, if you need to enforce a maximum buffer size or trigger a rotation/flush. - Remember that
APPENDsilently creates missing keys; use a consistent, namespaced key naming convention (likesession:abc123orlog:2026-08-10) so a typo is easy to spot withSCAN. - Set an explicit TTL with
EXPIREon any append-built buffer that isn’t meant to live forever, sinceAPPENDwon’t set one for you and won’t clear one you already set. - If you’re storing structured, growing data (fields that update independently), consider a hash (
HSET) instead of one big appended string — it’s easier to update individual pieces without re-parsing the whole blob. - Avoid
KEYS *to find keys you’ve been appending to; useSCANwith aMATCHpattern instead so you don’t block the server.
Practice Exercises
- Create a key
note:1with the text"Meeting at 3pm", then useAPPENDto add" in room 204"onto it. UseSTRLENto confirm the final length before and after checking the value withGET. - Without using
SETfirst, runAPPENDdirectly on a brand-new keyaudit:tempwith some text, then checkTTL audit:temp. What does it return, and why? Now add a 30-second expiration and append again — confirm the TTL is still counting down afterward. - Try running
STRLENon a key you’ve created withSADD(a set) instead of a string. Predict the result before you run it, then verify.
Summary
APPEND key valueadds bytes onto the end of an existing string, or creates the key fresh if it doesn’t exist yet; it returns the total length after the append.STRLEN keyreturns the byte length of a string in O(1) time, returning0for a key that doesn’t exist.APPENDis O(1) amortized thanks to Redis’s SDS over-allocation strategy, which avoids reallocating on every single call.- Both commands return a
WRONGTYPEerror on keys holding a non-string type. APPENDpreserves any existing TTL on the key — unlike a plainSET, which clears it unless you useKEEPTTL.APPENDconcatenates bytes; it is never the right tool for numeric increments — useINCR/INCRBYfor that.
