# SET

> Store a string value at a key, with optional expiry and conditions.

URL: https://docs.hotkv.com/commands/set/

```
SET key value [NX | XX | IFEQ value | IFNE value | IFDEQ digest | IFDNE digest] [GET] [EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL]
```

- Group: String
- Complexity: O(1)
- HotKV Cloud: all plans
- On-Premise: no license needed

`SET` stores `value` at `key`. If the key already holds a value, of any type,
it is overwritten and any existing time to live is cleared, unless you pass
`KEEPTTL`.

## Options

| Option | Effect |
| --- | --- |
| `NX` | Set only if the key does not exist. |
| `XX` | Set only if the key already exists. |
| `IFEQ value` | Set only if the key holds a string equal to `value`. |
| `IFNE value` | Set only if the key does not hold a string equal to `value`. A missing key is not equal to anything, so it is set. |
| `IFDEQ digest` | Set only if the [DIGEST](https://docs.hotkv.com/commands/digest/index.md) of the key's string equals `digest`. |
| `IFDNE digest` | Set only if the digest of the key's string does not equal `digest`. |
| `GET` | Return the previous string value (or nil) instead of `OK`. |
| `EX seconds` | Expire after this many seconds. |
| `PX milliseconds` | Expire after this many milliseconds. |
| `EXAT unix-time-seconds` | Expire at this Unix time, in seconds. |
| `PXAT unix-time-milliseconds` | Expire at this Unix time, in milliseconds. |
| `KEEPTTL` | Keep the key's current time to live. |

`NX`, `XX` and the four conditions `IFEQ`, `IFNE`, `IFDEQ` and `IFDNE` exclude one
another: give at most one of them, or the reply is `ERR syntax error`. Only one of
`EX`, `PX`, `EXAT`, `PXAT` and `KEEPTTL` can be given. Expiry values must be positive integers. An
absolute time that is already in the past deletes the key instead of setting
it.

## Return value

| Case | RESP2 | RESP3 |
| --- | --- | --- |
| Value stored | Simple string `OK` | Simple string `OK` |
| Not stored because of `NX`, `XX` or a condition | Nil bulk string | Null |
| With `GET` | The old value as a bulk string, or nil if the key did not exist | The old value, or null |

With `GET`, `SET` replies with a `WRONGTYPE` error if the key holds a value
that is not a string, and nothing is stored. With a condition and `GET`, the old
string comes back whether or not the condition held. A condition on a key that
holds another type is `WRONGTYPE` too.

## Examples

```
127.0.0.1:6379> SET greeting "hello"
OK
127.0.0.1:6379> SET greeting "hi" NX
(nil)
127.0.0.1:6379> SET greeting "hi" XX GET
"hello"
127.0.0.1:6379> SET session:42 "token" EX 3600
OK
127.0.0.1:6379> TTL session:42
(integer) 3600
127.0.0.1:6379> SET lock owner-a
OK
127.0.0.1:6379> SET lock owner-b IFEQ owner-x
(nil)
127.0.0.1:6379> SET lock owner-b IFEQ owner-a
OK
127.0.0.1:6379> SET lock owner-c IFNE owner-b
(nil)
127.0.0.1:6379> SET lock owner-d GET IFEQ nothing
"owner-b"
```

A condition lets you replace a value only when nobody else changed it since you
read it. `IFDEQ` and `IFDNE` compare the digest, so you do not have to send the
old value.

## Compatibility

Same options and replies as Redis 7 and Valkey 8, plus Redis 8.4's `IFEQ`, `IFNE`,
`IFDEQ` and `IFDNE`. For expiry with nanosecond
precision, see [NEXPIRE](https://docs.hotkv.com/commands/nexpire/index.md).

## See also

[GET](https://docs.hotkv.com/commands/get/index.md), [GETEX](https://docs.hotkv.com/commands/getex/index.md), [SETNX](https://docs.hotkv.com/commands/setnx/index.md),
[MSET](https://docs.hotkv.com/commands/mset/index.md), [EXPIRE](https://docs.hotkv.com/commands/expire/index.md)