{
  "schema_version": 2,
  "id": "develop/clients/hiredis/transpipe",
  "title": "Pipelines and transactions",
  "url": "https://redis.io/docs/latest/develop/clients/hiredis/transpipe/",
  "summary": "Learn how to use Redis pipelines and transactions",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-09-09T11:06:49+01:00",
  "page_type": "content",
  "content_hash": "5bcf4449fb6d24755db84078d4b299db46d5dff782a0d61ebd7f7eb268f8346f",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "Redis lets you send a sequence of commands to the server together in a batch.\nThere are two types of batch that you can use:\n\n-   **Pipelines** avoid network and processing overhead by sending several commands\n    to the server together in a single communication. The server then sends back\n    a single communication with all the responses. See the\n    [Pipelining](https://redis.io/docs/latest/develop/using-commands/pipelining) page for more\n    information.\n-   **Transactions** guarantee that all the included commands will execute\n    to completion without being interrupted by commands from other clients.\n    See the [Transactions](https://redis.io/docs/latest/develop/using-commands/transactions)\n    page for more information."
    },
    {
      "id": "execute-a-pipeline",
      "title": "Execute a pipeline",
      "role": "content",
      "text": "There is no command to explicitly start a pipeline with `hiredis`,\nbut if you issue a command with the `redisAppendCommand()` function,\nit will be added to an output buffer without being sent\nimmediately to the server.\n\nThere is also an input buffer that receives replies from\ncommands. If you call `redisGetReply()` when the input buffer is empty,\nit will first send any commands that are queued in the output buffer and\nthen wait for replies to arrive in the input buffer. It will then return\nthe first reply only.\n\nIf you then make subsequent `redisGetReply()` calls, they will\nfind the input buffer is not empty, but still has replies\nqueued from previous commands. In this case, `redisGetReply()`\nwill just remove and return replies from the input buffer\nuntil it is empty again.\n\nThe example below shows how to use `redisAppendCommand()`\nand `redisGetReply()` together:\n\n[code example]\n\n`redisAppendCommand()` has the same call signature as `redisCommand()` except that\nit doesn't return a `redisReply`. There is also a `redisAppendCommandArgv()`\nfunction that is analogous to `redisCommandArgv()` (see\n[Issue commands](https://redis.io/docs/latest/develop/clients/hiredis/issue-commands)\nfor more information).\n\n`redisGetReply()` receives the usual\ncontext pointer and a pointer to a `redisReply` pointer (which you\nmust cast to `void**`). After `redisGetReply()` returns,\nthe reply pointer will point to the `redisReply` object returned by\nthe queued command (see\n[Handle command replies](https://redis.io/docs/latest/develop/clients/hiredis/handle-replies)\nfor more information). \n\nCall `redisGetReply()` once for each command that you added to the pipeline.\nYou should check for errors after each call and free each reply object\nwhen you have finished processing it, as in the example above."
    },
    {
      "id": "transactions",
      "title": "Transactions",
      "role": "content",
      "text": "`hiredis` doesn't provide any special API to handle transactions, but\nyou can implement them yourself using the [`MULTI`](https://redis.io/docs/latest/commands/multi),\n[`EXEC`](https://redis.io/docs/latest/commands/exec), and [`WATCH`](https://redis.io/docs/latest/commands/watch)\ncommands as you would from [`redis-cli`](https://redis.io/docs/latest/develop/tools/cli).\nSee [Transactions](https://redis.io/docs/latest/develop/using-commands/transactions)\nfor more information."
    }
  ],
  "examples": [
    {
      "id": "execute-a-pipeline-ex0",
      "language": "c",
      "code": "redisAppendCommand(c, \"SET fruit:0 Apple\");\nredisAppendCommand(c, \"SET fruit:1 Banana\");\nredisAppendCommand(c, \"SET fruit:2 Cherry\");\n\nredisAppendCommand(c, \"GET fruit:0\");\nredisAppendCommand(c, \"GET fruit:1\");\nredisAppendCommand(c, \"GET fruit:2\");\n\n\nredisReply *reply;\n\n// Iterate once for each of the six commands in the\n// pipeline.\nfor (int i = 0; i < 6; ++i) {\n    redisGetReply(c, (void**) &reply);\n\n    // If an error occurs, the context object will\n    // contain an error code and/or an error string.\n    if (reply->type == REDIS_REPLY_ERROR) {\n        printf(\"Error: %s\", c->errstr);\n    } else {\n        printf(\"%s\\n\", reply->str);\n    }\n\n    freeReplyObject(reply);\n}\n// >>> OK\n// >>> OK\n// >>> OK\n// >>> Apple\n// >>> Banana\n// >>> Cherry",
      "section_id": "execute-a-pipeline"
    }
  ]
}
