{
  "schema_version": 2,
  "id": "commands/blpop",
  "title": "BLPOP",
  "url": "https://redis.io/docs/latest/commands/blpop/",
  "summary": "Removes and returns the first element in a list. Blocks until an element is available otherwise. Deletes the list if the last element was popped.",
  "since": "2.0.0",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-09-18T09:47:41+01:00",
  "page_type": "content",
  "content_hash": "d453f9e768247bdb1cf3d07229c94dc4107f205ae1ddbb6717023f19658a79d4",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "> [!NOTE]\n> This command's behavior varies in clustered Redis environments. See the [multi-key operations](https://redis.io/docs/latest/develop/using-commands/multi-key-operations) page for more information.\n\n\n`BLPOP` is a blocking list pop primitive.\nIt is the blocking version of [`LPOP`](https://redis.io/docs/latest/commands/lpop) because it blocks the connection when there\nare no elements to pop from any of the given lists.\nAn element is popped from the head of the first list that is non-empty, with the\ngiven keys being checked in the order that they are given."
    },
    {
      "id": "required-arguments",
      "title": "Required arguments",
      "role": "content",
      "text": "<details open><summary><code>key [key ...]</code></summary>\n\nOne or more keys of lists to operate on.\n\n</details>\n\n<details open><summary><code>timeout</code></summary>\n\nThe maximum time to block, in seconds. A timeout of `0` blocks indefinitely.\n\n</details>"
    },
    {
      "id": "examples",
      "title": "Examples",
      "role": "example",
      "text": "[code example]"
    },
    {
      "id": "details",
      "title": "Details",
      "role": "content",
      "text": ""
    },
    {
      "id": "non-blocking-behavior",
      "title": "Non-blocking behavior",
      "role": "content",
      "text": "When `BLPOP` is called, if at least one of the specified keys contains a\nnon-empty list, an element is popped from the head of the list and returned to\nthe caller together with the `key` it was popped from.\n\nKeys are checked in the order that they are given.\nLet's say that the key `list1` doesn't exist and `list2` and `list3` hold\nnon-empty lists.\nConsider the following command:\n\n[code example]\n\n`BLPOP` guarantees to return an element from the list stored at `list2` (since\nit is the first non empty list when checking `list1`, `list2` and `list3` in\nthat order)."
    },
    {
      "id": "blocking-behavior",
      "title": "Blocking behavior",
      "role": "content",
      "text": "If none of the specified keys exist, `BLPOP` blocks the connection until another\nclient performs an [`LPUSH`](https://redis.io/docs/latest/commands/lpush) or [`RPUSH`](https://redis.io/docs/latest/commands/rpush) operation against one of the keys.\n\nOnce new data is present on one of the lists, the client returns with the name\nof the key unblocking it and the popped value.\n\nWhen `BLPOP` causes a client to block and a non-zero timeout is specified,\nthe client will unblock returning a `nil` multi-bulk value when the specified\ntimeout has expired without a push operation against at least one of the\nspecified keys.\n\n**The timeout argument is interpreted as a double value specifying the maximum number of seconds to block**. A timeout of zero can be used to block indefinitely."
    },
    {
      "id": "what-key-is-served-first-what-client-what-element-priority-ordering-details",
      "title": "What key is served first? What client? What element? Priority ordering details.",
      "role": "content",
      "text": "* If the client tries to block for 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 this case, the client is not blocked. For example, `BLPOP key1 key2 key3 key4 0`, assuming that both `key2` and `key4` are non-empty, will always return an element from `key2`.\n\n* If multiple clients are blocked for the same key, the first client to be served is the one that has been waiting the longest (the first that blocked for the key). Once a client is unblocked it does not retain any priority; when it blocks again with another `BLPOP` call, it will be served according to its new position in the queue.\n\n* When a client is blocking for multiple keys and multiple keys become non-empty as a result of the same command, transaction, or Lua script, the client is served according to the **order of keys in its `BLPOP` call**, not the order of the write operations. After the writes occur, Redis reprocesses the blocking command for the client and pops from the **first non-empty key** in the key list.  \nFor example, a client blocked on `BLPOP key1 key2 0` will pop from `key1` if both `key1` and `key2` receive elements during the same `MULTI`/`EXEC` transaction, because `key1` appears first.\n\nInternally, when a write makes progress possible for a blocked client, Redis marks that client as unblocked (adding it to an internal queue). No reply is sent immediately. Before the server goes idle (in the `beforeSleep()` phase), Redis rechecks the blocking command and serves the client based on the first non-empty key in its provided key list.\n\n#### Example\n\n**Client A**\n\n[code example]\n\n**Client B**\n\n[code example]\n\nAlthough `key2` is pushed first inside the transaction, Redis reprocesses the blocking command for Client A after the transaction completes.  \nAt that time both lists are non-empty, and `BLPOP` pops from the first non-empty key in its argument list (`key1`):\n\n[code example]\n\nTo make Redis pop from `key2` instead, reverse the order of the keys in the blocking call:\n\n[code example]"
    },
    {
      "id": "behavior-of-blpop-when-multiple-elements-are-pushed-inside-a-list",
      "title": "Behavior of `BLPOP` when multiple elements are pushed inside a list.",
      "role": "content",
      "text": "There are times when a list can receive multiple elements in the context of the same conceptual command:\n\n* Variadic push operations such as `LPUSH mylist a b c`.\n* After an [`EXEC`](https://redis.io/docs/latest/commands/exec) of a [`MULTI`](https://redis.io/docs/latest/commands/multi) block with multiple push operations against the same list.\n* Executing a Lua Script with Redis 2.6 or newer.\n\nWhen multiple elements are pushed inside a list where there are clients blocking, the behavior is different for Redis 2.4 and Redis 2.6 or newer.\n\nFor Redis 2.6 what happens is that the command performing multiple pushes is executed, and *only after* the execution of the command the blocked clients are served. Consider this sequence of commands.\n\n    Client A:   BLPOP foo 0\n    Client B:   LPUSH foo a b c\n\nIf the above condition happens using a Redis 2.6 server or greater, Client **A** will be served with the `c` element, because after the [`LPUSH`](https://redis.io/docs/latest/commands/lpush) command the list contains `c,b,a`, so taking an element from the left means to return `c`.\n\nInstead Redis 2.4 works in a different way: clients are served *in the context* of the push operation, so as long as `LPUSH foo a b c` starts pushing the first element to the list, it will be delivered to the Client **A**, that will receive `a` (the first element pushed).\n\nThe behavior of Redis 2.4 creates a lot of problems when replicating or persisting data into the AOF file, so the much more generic and semantically simpler behavior was introduced into Redis 2.6 to prevent problems.\n\nNote 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 this case the blocked clients will not be served at all and will continue to be blocked as long as no data is present on the list after the execution of a single command, transaction, or script."
    },
    {
      "id": "blpop-inside-a-multi--exec-transaction",
      "title": "`BLPOP` inside a `MULTI` / `EXEC` transaction",
      "role": "content",
      "text": "`BLPOP` can be used with pipelining (sending multiple commands and\nreading the replies in batch), however this setup makes sense almost solely\nwhen it is the last command of the pipeline.\n\nUsing `BLPOP` inside a [`MULTI`](https://redis.io/docs/latest/commands/multi) / [`EXEC`](https://redis.io/docs/latest/commands/exec) block does not make a lot of sense\nas it would require blocking the entire server in order to execute the block\natomically, which in turn does not allow other clients to perform a push\noperation. For this reason the behavior of `BLPOP` inside [`MULTI`](https://redis.io/docs/latest/commands/multi) / [`EXEC`](https://redis.io/docs/latest/commands/exec) when the list is empty is to return a `nil` multi-bulk reply, which is the same\nthing that happens when the timeout is reached.\n\nIf you like science fiction, think of time flowing at infinite speed inside a\n[`MULTI`](https://redis.io/docs/latest/commands/multi) / [`EXEC`](https://redis.io/docs/latest/commands/exec) block..."
    },
    {
      "id": "reliable-queues",
      "title": "Reliable queues",
      "role": "content",
      "text": "When `BLPOP` returns an element to the client, it also removes the element from the list. This means that the element only exists in the context of the client: if the client crashes while processing the returned element, it is lost forever.\n\nThis can be a problem with some application where we want a more reliable messaging system. When this is the case, please check the [`BRPOPLPUSH`](https://redis.io/docs/latest/commands/brpoplpush) command, that is a variant of `BLPOP` that adds the returned element to a target list before returning it to the client."
    },
    {
      "id": "pattern-event-notification",
      "title": "Pattern: event notification",
      "role": "content",
      "text": "Using blocking list operations it is possible to mount different blocking\nprimitives.\nFor instance for some application you may need to block waiting for elements\ninto a Redis Set, so that as far as a new element is added to the Set, it is\npossible to retrieve it without resort to polling.\nThis would require a blocking version of [`SPOP`](https://redis.io/docs/latest/commands/spop) that is not available, but using\nblocking list operations we can easily accomplish this task.\n\nThe consumer will do:\n\n[code example]\n\nWhile in the producer side we'll use simply:\n\n[code example]"
    },
    {
      "id": "redis-software-and-redis-cloud-compatibility",
      "title": "Redis Software and Redis Cloud compatibility",
      "role": "content",
      "text": "| Redis<br />Software | Redis<br />Cloud | <span style=\"min-width: 9em; display: table-cell\">Notes</span> |\n|:----------------------|:-----------------|:------|\n| <span title=\"Supported\">&#x2705; Standard</span><br /><span title=\"Supported\"><nobr>&#x2705; Active-Active</nobr></span> | <span title=\"Supported\">&#x2705; Standard</span><br /><span title=\"Supported\"><nobr>&#x2705; Active-Active</nobr></span> |  |"
    },
    {
      "id": "return-information",
      "title": "Return information",
      "role": "returns",
      "text": "**RESP2:**\n\nOne of the following:\n* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): no element could be popped and the timeout expired\n* [Array reply](../../develop/reference/protocol-spec#arrays): the key from which the element was popped and the value of the popped element.\n\n**RESP3:**\n\nOne of the following:\n* [Null reply](../../develop/reference/protocol-spec#nulls): no element could be popped and the timeout expired\n* [Array reply](../../develop/reference/protocol-spec#arrays): the key from which the element was popped and the value of the popped element."
    }
  ],
  "examples": [
    {
      "id": "examples-ex0",
      "language": "plaintext",
      "code": "redis> DEL list1 list2\n(integer) 0\nredis> RPUSH list1 a b c\n(integer) 3\nredis> BLPOP list1 list2 0\n1) \"list1\"\n2) \"a\"",
      "section_id": "examples"
    },
    {
      "id": "non-blocking-behavior-ex0",
      "language": "plaintext",
      "code": "BLPOP list1 list2 list3 0",
      "section_id": "non-blocking-behavior"
    },
    {
      "id": "what-key-is-served-first-what-client-what-element-priority-ordering-details-ex0",
      "language": "plaintext",
      "code": "BLPOP key1 key2 0",
      "section_id": "what-key-is-served-first-what-client-what-element-priority-ordering-details"
    },
    {
      "id": "what-key-is-served-first-what-client-what-element-priority-ordering-details-ex1",
      "language": "plaintext",
      "code": "MULTI\nRPUSH key2 1 2 3 4\nRPUSH key1 5 6 7\nEXEC",
      "section_id": "what-key-is-served-first-what-client-what-element-priority-ordering-details"
    },
    {
      "id": "what-key-is-served-first-what-client-what-element-priority-ordering-details-ex2",
      "language": "plaintext",
      "code": "\"key1\"\n\"5\"",
      "section_id": "what-key-is-served-first-what-client-what-element-priority-ordering-details"
    },
    {
      "id": "what-key-is-served-first-what-client-what-element-priority-ordering-details-ex3",
      "language": "plaintext",
      "code": "BLPOP key2 key1 0",
      "section_id": "what-key-is-served-first-what-client-what-element-priority-ordering-details"
    },
    {
      "id": "pattern-event-notification-ex0",
      "language": "plaintext",
      "code": "LOOP forever\n    WHILE SPOP(key) returns elements\n        ... process elements ...\n    END\n    BRPOP helper_key\nEND",
      "section_id": "pattern-event-notification"
    },
    {
      "id": "pattern-event-notification-ex1",
      "language": "plaintext",
      "code": "MULTI\nSADD key element\nLPUSH helper_key x\nEXEC",
      "section_id": "pattern-event-notification"
    }
  ]
}
