Skip to main content
Cache-Pot transactions let you queue a series of commands and execute them atomically with MULTI/EXEC. Between MULTI and EXEC, every command you send is acknowledged with QUEUED rather than being run immediately. When you call EXEC, all queued commands run in order and their results are returned as an array. Use WATCH for optimistic locking — if any watched key is modified by another client before you call EXEC, the transaction is automatically aborted.
Unlike single-threaded Redis, Cache-Pot does not hold a global lock during EXEC. Each queued command is individually atomic, and WATCH correctly detects concurrent changes to watched keys, but commands from other connections can interleave between your queued commands. This best-effort isolation is sufficient for the common optimistic lock pattern.

MULTI

Begins a transaction block. All subsequent commands are queued rather than executed, and each is acknowledged with +QUEUED. Nested MULTI calls are not allowed — Cache-Pot returns an error if you issue MULTI while already inside a transaction. Syntax: MULTI
Returns: OK.

EXEC

Executes all commands queued since MULTI and returns their results as an array. Exits the transaction block automatically. If WATCH was active and any watched key changed since it was watched, EXEC aborts and returns a null array — nothing is executed. If a command was queued that could not be recognised (unknown command, or a forbidden command like SUBSCRIBE or MONITOR), the transaction is marked dirty and EXEC returns an EXECABORT error without running anything. Syntax: EXEC
Returns: Array of replies from each queued command, in order. Returns a null array if a watched key was modified. Returns an EXECABORT error if the transaction was dirtied by an invalid queued command.

DISCARD

Aborts the current transaction, clears all queued commands, releases all WATCHes, and exits the transaction block. Has no effect on data. Syntax: DISCARD
Returns: OK, or an error if called outside a MULTI block.

WATCH

Marks one or more keys for optimistic locking. If any watched key is written to by any client between the WATCH call and EXEC, the transaction is aborted and EXEC returns a null array. WATCH must be called before MULTI. Syntax: WATCH key [key ...]
Returns: OK. Returns an error if called inside an active MULTI block.

UNWATCH

Releases all keys currently being watched by this connection, without aborting a transaction. Calling EXEC or DISCARD also releases watches automatically. Syntax: UNWATCH
Returns: OK.

Example: atomic counter update

The simplest transaction: increment a counter and record the timestamp in a single atomic operation.

Example: optimistic locking with retry

Use WATCH to implement a compare-and-swap. If the transaction aborts, re-read the value and retry:
Wrap your WATCH + MULTI + EXEC sequence in a retry loop in your application. A null reply from EXEC is not an error — it is a normal signal to re-read the latest state and try again.
The commands SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, and MONITOR cannot be queued inside a MULTI block. Attempting to queue any of them marks the transaction as dirty — the subsequent EXEC will return EXECABORT and run nothing.