{
  "schema_version": 2,
  "id": "operate/oss_and_stack/stack-with-enterprise/deprecated-features/triggers-and-functions/concepts/Binary_Data",
  "title": "Binary data",
  "url": "https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/deprecated-features/triggers-and-functions/concepts/binary_data/",
  "summary": "Working with binary data",
  "aliases": [
    "/develop/interact/programmability/triggers-and-functions/concepts/binary_data/"
  ],
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-09-21T16:36:38+01:00",
  "page_type": "content",
  "content_hash": "2950cf5037ff406c529144fc683fac987c063810e2089b542859aa9f7251dd8e",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "By default, triggers and functions will decode all data as a string and will raise error on failures. Though useful for most users, sometimes there is a need to work with binary data. In order to do so, the library developer has to consider the following:\n\n1. Binary function arguments\n2. Binary command results\n3. Binary key names on [keyspace triggers](https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/deprecated-features/triggers-and-functions/concepts/triggers/KeySpace_Triggers)\n4. Binary data on [stream triggers](https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/deprecated-features/triggers-and-functions/concepts/triggers/Stream_Triggers)"
    },
    {
      "id": "binary-function-arguments",
      "title": "Binary function arguments",
      "role": "content",
      "text": "It is possible to instruct triggers and functions not to decode function arguments as `JS` `Strings` using the [redis.functionFlags.RAW_ARGUMENTS](https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/deprecated-features/triggers-and-functions/concepts/Function_Flags) function flag. In this case, the function arguments will be given as `JS` `ArrayBuffer`. Example:\n\n[code example]\n\nThe above example will allow us to set `key` and `val` even if those are binary data. Run example:\n\n[code example]\n\nNotice that the `call` function also accepts `JS` `ArrayBuffer` arguments."
    },
    {
      "id": "binary-command-results",
      "title": "Binary command results",
      "role": "content",
      "text": "Getting function arguments as binary data is not enough. We might want to read binary data from a Redis key. In order to do this we can use the `callRaw` function, which will not decode the result as a `JS` `String` and instead will return the result as a `JS` `ArrayBuffer`. Example:\n\n[code example]\n\nThe above example will be able to fetch binary data and return it to the user. For example:\n\n[code example]\n\nNotice that a `JS` `ArrayBuffer` can be returned by a function, it will be returned to the client as `bulk string`."
    },
    {
      "id": "binary-keys-names-on-database-triggers",
      "title": "Binary keys names on database triggers",
      "role": "content",
      "text": "On [keyspace triggers](https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/deprecated-features/triggers-and-functions/concepts/triggers/KeySpace_Triggers), if the key name that triggered the event is binary, the `data.key` field will be NULL. The `data.key_raw` field is always provided as a `JS` `ArrayBuffer` and can be used as in the following example:\n\n[code example]\n\nRun example:\n\n[code example]\n\nFor more information see [keyspace triggers](https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/deprecated-features/triggers-and-functions/concepts/triggers/KeySpace_Triggers)."
    },
    {
      "id": "binary-data-on-stream-consumers",
      "title": "Binary data on stream consumers",
      "role": "content",
      "text": "On [stream triggers](https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/deprecated-features/triggers-and-functions/concepts/triggers/Stream_Triggers), if the key name is binary. The `data.stream_name` field will be NULL. The `data.stream_name_raw` field is always provided as a `JS` `ArrayBuffer` and can be used in this case. In addition, if the content of the steam is binary, it will also appear as `null` under `data.record`. In this case, it is possible to use `data.record` (which always exists) and contains the data as a `JS` `ArrayBuffer`. Example:\n\n[code example]\n\nRun Example:\n\n[code example]"
    }
  ],
  "examples": [
    {
      "id": "binary-function-arguments-ex0",
      "language": "js",
      "code": "#!js api_version=1.0 name=lib\nredis.registerFunction(\"my_set\",\n    (c, key, val) => {\n        return c.call(\"set\", key, val);\n    },\n    {\n        flags: [redis.functionFlags.RAW_ARGUMENTS]\n    }\n);",
      "section_id": "binary-function-arguments"
    },
    {
      "id": "binary-function-arguments-ex1",
      "language": "bash",
      "code": "127.0.0.1:6379> TFCALL lib.my_set 1 \"\\xaa\" \"\\xaa\"\n\"OK\"\n127.0.0.1:6379> get \"\\xaa\"\n\"\\xaa\"",
      "section_id": "binary-function-arguments"
    },
    {
      "id": "binary-command-results-ex0",
      "language": "js",
      "code": "#!js api_version=1.0 name=lib\nredis.registerFunction(\"my_get\", \n    (c, key) => {\n        return c.callRaw(\"get\", key);\n    },\n    {\n        flags: [redis.functionFalgs.RAW_ARGUMENTS]\n    }\n);",
      "section_id": "binary-command-results"
    },
    {
      "id": "binary-command-results-ex1",
      "language": "bash",
      "code": "27.0.0.1:6379> set \"\\xaa\" \"\\xaa\"\nOK\n127.0.0.1:6379> TFCALL lib.my_get 1 \"\\xaa\"\n\"\\xaa\"",
      "section_id": "binary-command-results"
    },
    {
      "id": "binary-keys-names-on-database-triggers-ex0",
      "language": "js",
      "code": "#!js api_version=1.0 name=lib\n/* The following is just an example, in general it is discourage to use globals. */\nvar n_notifications = 0;\nvar last_key = null;\nvar last_key_raw = null;\nredis.registerKeySpaceTrigger(\"consumer\", \"\", function(client, data) {\n    if (data.event == \"set\") {\n        n_notifications += 1;\n        last_data = data.key;\n        last_key_raw = data.key_raw;\n    }\n});\n\nredis.registerFunction(\"notifications_stats\", async function(){\n    return [\n        n_notifications,\n        last_key,\n        last_key_raw\n    ];\n});",
      "section_id": "binary-keys-names-on-database-triggers"
    },
    {
      "id": "binary-keys-names-on-database-triggers-ex1",
      "language": "bash",
      "code": "127.0.0.1:6379> set \"\\xaa\" \"\\xaa\"\nOK\n127.0.0.1:6379> TFCALL lib.notifications_stats 0\n1) (integer) 1\n2) (nil)\n3) \"\\xaa\"",
      "section_id": "binary-keys-names-on-database-triggers"
    },
    {
      "id": "binary-data-on-stream-consumers-ex0",
      "language": "js",
      "code": "#!js api_version=1.0 name=lib\n/* The following is just an example, in general it is discourage to use globals. */\nvar last_key = null;\nvar last_key_raw = null;\nvar last_data = null;\nvar last_data_raw = null;\nredis.registerFunction(\"stats\", function(){\n    return [\n        last_key,\n        last_key_raw,\n        last_data,\n        last_data_raw\n    ];\n})\nredis.registerStreamTrigger(\"consumer\", new Uint8Array([255]).buffer, function(c, data){\n    last_key = data.stream_name;\n    last_key_raw = data.stream_name_raw;\n    last_data = data.record;\n    last_data_raw = data.record_raw;\n})",
      "section_id": "binary-data-on-stream-consumers"
    },
    {
      "id": "binary-data-on-stream-consumers-ex1",
      "language": "bash",
      "code": "127.0.0.1:6379> xadd \"\\xff\\xff\" * \"\\xaa\" \"\\xaa\"\n\"1659515146671-0\"\n127.0.0.1:6379> TFCALL foo.stats 0\n1) (nil)\n2) \"\\xff\\xff\"\n3) 1) 1) (nil)\n      2) (nil)\n4) 1) 1) \"\\xaa\"\n      2) \"\\xaa\"",
      "section_id": "binary-data-on-stream-consumers"
    }
  ]
}
