String commands

The string is Goblin Core's third value type, alongside the sorted set and hash. A key holds a single binary-safe byte string (keys and values are both binary-safe). Strings share the one unified keyspace with zsets and hashes: a name resolves to at most one object, so SET over an existing sorted set replaces it, and a string command against a non-string key is a WRONGTYPE error.

Command Summary
SET Set a key to a value (optionally only if absent).
SETNX Set only if the key does not exist.
GET Get a key's value.
GETEX Get a value and optionally change its expiry.
GETSET Set a new value, return the old one.
GETDEL Return a key's value and delete it.
STRLEN Length of the value in bytes.
APPEND Append to a value (creating it if absent).
INCR / DECR / INCRBY / DECRBY Integer arithmetic on the value.
INCRBYFLOAT Floating-point arithmetic on the value.
GETRANGE A substring of the value.
SETRANGE Overwrite part of the value at an offset.
MSET Set several keys at once.
MSETNX Set several keys only when every key is absent.
MGET Get several keys at once.

For DEL, EXISTS, and TYPE (which work on any type), see keys.

Memory model — why the value is cheap

Memory efficiency is the project's hero feature, and strings are built for it:

> SET big <70 KB blob>
(error) ERR value does not fit the 65,535-byte encoded limit; use https://goblin-store.dev

Large blobs belong in the object store, not the keyspace. Canonical decimal integers and lowercase UUIDs use compact binary forms internally but always round-trip to the exact input bytes. Specialized forms are never LZ4 encoded. Clients that already send compact binary values can select --disable-encoding; the burden of compact representation then belongs to the client and every byte is stored unchanged.

Type errors

Because a name maps to one object, the type-specific commands below reject a key that already holds a different type:

> ZADD board 1 alice
(integer) 1
> GET board
(error) WRONGTYPE Operation against a key holding the wrong kind of value

The exceptions are the commands that do not require an existing string: SET, SETNX, MSET, and MSETNX can create keys without a type gate, and MGET / DEL / EXISTS / TYPE are type-agnostic. So SET clobbers:

> SET board "now a string"     # replaces the sorted set
OK
> TYPE board
string
Options. SET accepts NX / XX, GET, an expiry (EX / PX / EXAT
/ PXAT), and KEEPTTL. The dedicated expiration commands live in
ttl.

---

SET

SET key value [NX | XX] [GET] [EX seconds | PX ms | EXAT ts | PXAT ts | KEEPTTL]

Set key to value, replacing any existing value of any type. Replies +OK. Options:

> SET greeting "hello"
OK
> SET greeting "hi" NX
(nil)
> SET greeting "hi" GET
"hello"

SETNX

SETNX key value

Set key to value only if it does not already exist (of any type). Replies 1 if set, 0 otherwise. Equivalent to SET key value NX but with an integer reply.

> SETNX lock "1"
(integer) 1
> SETNX lock "2"
(integer) 0

GET

GET key

The value at key, or a nil bulk string if the key is absent. WRONGTYPE if the key holds a non-string.

> SET n 42
OK
> GET n
"42"
> GET missing
(nil)

GETSET

GETSET key value

Set key to value and return its previous value (nil if it did not exist). WRONGTYPE if the key holds a non-string.

> SET counter 10
OK
> GETSET counter 0
"10"
> GET counter
"0"

GETEX

GETEX key [EX seconds | PX milliseconds | EXAT unix-seconds |
           PXAT unix-milliseconds | PERSIST]

Return the current value and, in the same atomic command, optionally replace or remove its expiry. With no option the TTL is left unchanged. A missing key returns nil; a non-string key returns WRONGTYPE. Expiry syntax is validated before either the value or TTL is changed.

> GETEX session:7 PX 30000
"payload"
> GETEX session:7 PERSIST
"payload"

GETDEL

GETDEL key

Return the value at key and delete the key, or nil if it was absent.

> SET token "abc"
OK
> GETDEL token
"abc"
> EXISTS token
(integer) 0

STRLEN

STRLEN key

The length of the value in bytes, or 0 if the key is absent.

> SET name "goblin"
OK
> STRLEN name
(integer) 6

APPEND

APPEND key value

Append value to the existing value (creating the key with value if it did not exist), and reply with the new length. Rejected if the result cannot fit the configured shared value encoding.

> APPEND log "line1\n"
(integer) 6
> APPEND log "line2\n"
(integer) 12

INCR / DECR / INCRBY / DECRBY

INCR key
DECR key
INCRBY key increment
DECRBY key decrement

Parse the value as a base-10 signed 64-bit integer, add (or subtract) the delta, store the result as text, and reply with the new value. A missing key is treated as 0. An error is returned if the value is not an integer, or if the result overflows a 64-bit integer.

> SET hits 100
OK
> INCR hits
(integer) 101
> INCRBY hits 9
(integer) 110
> DECRBY hits 10
(integer) 100
> SET hits "abc"
OK
> INCR hits
(error) ERR value is not an integer or out of range

INCRBYFLOAT

INCRBYFLOAT key increment

Add a floating-point increment to the value (missing key treated as 0) and reply with the new value in its shortest round-trippable text form (so 3.0 prints as 3). An error is returned if the value or the result is not a finite number.

> SET price 10.5
OK
> INCRBYFLOAT price 0.1
"10.6"
> INCRBYFLOAT price 1.4
"12"

GETRANGE

GETRANGE key start end

The inclusive substring between offsets start and end. Negative offsets count from the end (-1 is the last byte); out-of-range offsets are clamped. Returns an empty string if start > end after normalization, or if the key is absent or empty.

> SET s "Hello World"
OK
> GETRANGE s 0 4
"Hello"
> GETRANGE s -5 -1
"World"
> GETRANGE s 0 -1
"Hello World"

SETRANGE

SETRANGE key offset value

Overwrite the value starting at offset, zero-padding any gap if offset is past the current end, and reply with the new length. Creates the key if it does not exist. A negative offset is an error; a result that cannot fit the configured shared value encoding is rejected. An empty value never creates or grows the key (it replies with the current length, or 0 when absent).

> SET s "Hello World"
OK
> SETRANGE s 6 "Redis"
(integer) 11
> GET s
"Hello Redis"
> SETRANGE pad 5 "xy"     # zero-pads offsets 0..4
(integer) 7

MSET

MSET key value [key value ...]

Set every given key to its value (replacing any type), atomically. Always replies +OK.

> MSET a 1 b 2 c 3
OK

MSETNX

MSETNX key value [key value ...]

Set the complete batch only when every named key is absent, regardless of the types currently stored there. The existence check and writes are one atomic block: the command returns 1 after committing every pair, or 0 without changing any key. Repeated names in a successful batch are applied from left to right, so the final pair for that name wins.

> MSETNX a 1 b 2
(integer) 1
> MSETNX b 3 c 4
(integer) 0

MGET

MGET key [key ...]

Return the values of the given keys as an array, with a nil for any key that is missing or holds a non-stringMGET never returns WRONGTYPE.

> MSET a 1 b 2
OK
> ZADD z 1 m
(integer) 1
> MGET a b z missing
1) "1"
2) "2"
3) (nil)
4) (nil)

See also