BLPOP(3valkey)
hey bestie π welcome to the BLPOP page from the Valkey Command Manual β yes the whole thing, every flag, every caveat, no skips, no cap. grab a boba, we're doing this. π§β¨
π NAME π
blpop β pulls the first element off a list and hands it to you, and if there's literally nothing there it just waits (blocks) until something shows up. If you pop the very last element, the list gets yeeted into the void β deleted. π
β¨ SYNOPSIS β¨
BLPOP key [key...] timeout
π¦ DESCRIPTION π¦
BLPOP is the blocking list-pop primitive, okay? It's the blocking twin of valkey-lpop(7) LPOP, because it blocks the connection whenever there's nothing to pop from any of the lists you gave it. An element gets popped from the head of the first list that's non-empty, and your keys get checked in the exact order you typed them. no reshuffling, no vibes-based ordering. π
π Non-blocking behavior π
When you call BLPOP, if at least one of the keys you named holds a non-empty list, an element gets popped off the head and handed back to you together with the key it came from. two-for-one, iconic. π«Ά
Keys are checked in the order given. So like, say the key list1 doesn't exist, but list2 and list3 are both holding non-empty lists. Look at this command:
BLPOP list1 list2 list3 0
BLPOP guarantees it returns an element from the list stored at list2 β because list2 is the first non-empty list when you check list1, list2, list3 in that order. it's giving first-come-first-served. π
πΈ Blocking behavior πΈ
If none of the keys you named exist, BLPOP blocks the connection until some other client runs an valkey-lpush(7) LPUSH or an valkey-rpush(7) RPUSH against one of those keys. like, it's just sitting there. waiting. main character patience. π
Once new data shows up on one of the lists, the client comes back with the name of the key that unblocked it and the popped value.
When BLPOP makes a client block and you specified a non-zero timeout, the client unblocks and returns a nil multi-bulk value if the specified timeout expires without a push operation hitting at least one of the specified keys. the wait had a limit, bestie.
The timeout argument is interpreted as a double value β it's the max number of seconds to block. And a timeout of 0 means block indefinitely. forever. until the end of time. β³
π What key is served first? What client? What element? Priority ordering details. π
- If a client is trying to block on multiple keys but at least one key contains elements, the returned key / element pair is the first key from left to right that has one or more elements. In that case the client is not blocked. So for instance
BLPOP key1 key2 key3 key4 0, assuming bothkey2andkey4are non-empty, will always return an element fromkey2. π― - If multiple clients are blocked on the same key, the first client to be served is the one that's been waiting longer β the first one that blocked on that key. Once a client is unblocked it does not keep any priority; when it blocks again on the next
BLPOPcall, it gets served according to how many clients are already blocked on the same key, and all of those get served before it (from the first to the last that blocked). no permanent VIP pass, sorry. π - When a client is blocking on multiple keys at the same time, and elements become available at the same time in multiple keys (because a transaction or a Lua script added elements to multiple lists), the client gets unblocked using the first key that received a push operation β assuming that key has enough elements to serve our client, since there might be other clients waiting on it too. Basically, after every command executes, Valkey runs through a list of all the keys that received data AND that have at least one client blocked. That list is ordered by new element arrival time, from the first key that received data to the last. For every key processed, Valkey serves all the clients waiting on that key in FIFO fashion, for as long as there are elements in that key. When the key is empty or there are no longer clients waiting on it, the next key that received new data in the previous command / transaction / script gets processed, and so on. π
π₯ Behavior of BLPOP when multiple elements are pushed inside a list. π₯
Sometimes a list can receive multiple elements within the context of the same conceptual command:
- Variadic push operations such as
LPUSH mylist a b c. π - After an
valkey-exec(7)EXECof avalkey-multi(7)MULTIblock with multiple push operations against the same list. - Executing a Lua Script.
What happens is: the command doing the multiple pushes executes, and only after that command finishes do the blocked clients get served. Consider this sequence of commands:
Client A: BLPOP foo 0
Client B: LPUSH foo a b c
If the above condition happens using a Redis OSS 2.6 server or greater, Client A gets served with the c element β because after the LPUSH command the list contains c,b,a, so taking an element from the left means returning c. wild, right? π
Note that for the same reason, a Lua script or a MULTI/EXEC block may push elements into a list and afterward delete the list. In that case the blocked clients won't be served at all, and they'll keep on being blocked for as long as no data is present on the list after the execution of a single command, transaction, or script. π«
π BLPOP inside a MULTI / EXEC transaction π
BLPOP can be used with pipelining (sending multiple commands and reading the replies in batch), however this setup makes sense almost solely when it's the last command of the pipeline. yeah. only then.
Using BLPOP inside a MULTI/EXEC block doesn't make a lot of sense, because it would require blocking the entire server in order to execute the block atomically β which in turn wouldn't let other clients perform a push operation. so it's kind of a self-own. For this reason the behavior of BLPOP inside MULTI / EXEC when the list is empty is to return a nil multi-bulk reply β the exact same thing that happens when the timeout is reached. β¨
If you like science fiction, think of time flowing at infinite speed inside a MULTI / EXEC block... πΈ
π REPLY π
π©΅ RESP2 π©΅
One of the following:
valkey-protocol(7)Nil reply: no element could be popped and the timeout expired.valkey-protocol(7)Array reply: the key from which the element was popped and the value of the popped element.
π RESP3 π
One of the following:
valkey-protocol(7)Null reply: no element could be popped and the timeout expired.valkey-protocol(7)Array reply: the key from which the element was popped and the value of the popped element.
π₯ COMPLEXITY π₯
O(N) where N is the number of provided keys.
π ACL CATEGORIES π
@blocking @list @slow @write
β HISTORY β
- Available since: 2.0.0
- Changed in 6.0.0:
timeoutis interpreted as a double instead of an integer. glow up. β¨
π EXAMPLES π
127.0.0.1:6379> DEL list1 list2
(integer) 0
127.0.0.1:6379> RPUSH list1 a b c
(integer) 3
127.0.0.1:6379> BLPOP list1 list2 0
1) "list1"
2) "a"
π§ Reliable queues π§
When BLPOP returns an element to the client, it also removes the element from the list. Which means that element only exists in the context of your client: if the client crashes while it's still processing that returned element, it is lost forever. π
This can be a problem for applications where you want a more reliable messaging system. When that's the case, please check the valkey-brpoplpush(7) BRPOPLPUSH command β it's a variant of BLPOP that adds the returned element to a target list before returning it to the client. saving lives fr fr. π«Ά
π¦ Pattern: Event notification π¦
Using blocking list operations you can mount all sorts of different blocking primitives. For instance, some application might need to block waiting for elements into a Set, so that as soon as a new element is added to the Set, you can retrieve it without resorting to polling. That would require a blocking version of valkey-spop(7) SPOP β which is not available β but using blocking list operations we can easily accomplish this task. π§ β¨
The consumer will do:
LOOP forever
WHILE SPOP(key) returns elements
... process elements ...
END
BRPOP helper_key
END
While on the producer side we'll simply use:
MULTI
SADD key element
LPUSH helper_key x
EXEC
π SEE ALSO π
blmove(3valkey), blmpop(3valkey), brpop(3valkey), brpoplpush(3valkey), lindex(3valkey), linsert(3valkey), llen(3valkey), lmove(3valkey), lmpop(3valkey), lpop(3valkey), lpos(3valkey), lpush(3valkey), lpushx(3valkey), lrange(3valkey), lrem(3valkey), lset(3valkey), ltrim(3valkey), rpop(3valkey), rpoplpush(3valkey), rpush(3valkey), rpushx(3valkey)
and that's the whole page bestie π
this one's from Valkey 9.0.0, dated 2025-10-21 β go forth and block responsibly π«Άβ¨
π¦ where this page comes from
- fedora 44: valkey-doc 9.0.3-2.fc44 Β· CC-BY-SA-4.0
- fedora 44: valkey-doc 9.0.6-1.fc44 Β· CC-BY-SA-4.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms