{
  "schema_version": 2,
  "id": "operate/oss_and_stack/stack-with-enterprise/json/active-active",
  "title": "Store JSON in Active-Active databases",
  "url": "https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/json/active-active/",
  "summary": "JSON support and conflict resolution rules for Active-Active databases.",
  "tags": [
    "docs",
    "operate",
    "stack"
  ],
  "last_updated": "2026-10-02T14:53:57+01:00",
  "page_type": "content",
  "content_hash": "6c4123473061707c2506a20dc363ce197552502fafabc214fa4abde9ec4502a1",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "RedisJSON v2.2 adds support for JSON in [Active-Active Redis Software databases](https://redis.io/docs/latest/operate/rs/databases/active-active).\n\nThe design is based on [A Conflict-Free Replicated JSON Datatype](https://arxiv.org/abs/1608.03960) by Kleppmann and Beresford, but the implementation includes some changes. Several [conflict resolution rule](#conflict-resolution-rules) examples were adapted from this paper as well."
    },
    {
      "id": "create-an-active-active-json-database",
      "title": "Create an Active-Active JSON database",
      "role": "content",
      "text": "To use JSON in an Active-Active database, you must enable JSON during database creation.\n\nActive-Active Redis Cloud databases add JSON by default. See [Create an Active-Active database](https://redis.io/docs/latest/operate/rc/databases/active-active/create-active-active-database#select-capabilities) in the Redis Cloud documentation for details.\n\nIn Redis Software, Active-Active databases created with or upgraded to Redis version 8 or later automatically enable JSON. For earlier Redis versions, you can enable JSON during database creation:\n\n1. See [Create an Active-Active geo-replicated database](https://redis.io/docs/latest/operate/rs/databases/active-active/create) in the Redis Software documentation for prerequisites and detailed steps.\n\n1. In the **Capabilities** section of the **Create Active-Active database** screen, select **JSON**:\n\n    ![Select JSON from the Capabilities section.](https://redis.io/docs/latest/images/rs/screenshots/databases/active-active-databases/create-a-a-db-json-search.png)\n\n    > [!NOTE]\n    > When you select **JSON**, **Search and Query** is also selected by default to allow you to index and query JSON documents. If you do not want to use these additional features, you can clear the **Search and Query** check box.\n    >     \n\n1. Configure additional database settings.\n\n1. Select **Create**."
    },
    {
      "id": "command-differences",
      "title": "Command differences",
      "role": "syntax",
      "text": "Some JSON commands work differently for Active-Active databases."
    },
    {
      "id": "jsonclear",
      "title": "`JSON.CLEAR`",
      "role": "content",
      "text": "[`JSON.CLEAR`](https://redis.io/docs/latest/commands/json.clear) resets JSON arrays and objects. It supports concurrent updates to JSON documents from different instances in an Active-Active database and allows the results to be merged."
    },
    {
      "id": "conflict-resolution-rules",
      "title": "Conflict resolution rules",
      "role": "content",
      "text": "With Active-Active databases, it's possible for two different instances to try to run write operations on the same data at the same time. If this happens, conflicts can arise when the replicas attempt to sync these changes with each other. Conflict resolution rules determine how the database handles conflicting operations.\n\nThere are two types of conflict resolution:\n\n1. Merge:\n\n    - The operations are associative.\n\n    - Merges the results of both operations.\n\n1. Win over:\n\n    - The operations are not associative.\n\n    - One operation wins the conflict and sets the value.\n\n    - Ignores the losing operation.\n\nThe following conflict resolution rules show how Active-Active databases resolve conflicts for various JSON commands."
    },
    {
      "id": "assign-different-types-to-a-key",
      "title": "Assign different types to a key",
      "role": "content",
      "text": "**Conflict**\n\nTwo instances concurrently assign values of different types to the same key within a JSON document.\n\nFor example:\n\nInstance 1 assigns an object to a key within a JSON document.\n\nInstance 2 assigns an array to the same key.\n\n**Resolution type**\n\nWin over\n\n**Resolution rule**\n\nThe instance with the smaller ID wins, so the key becomes an object in the given example.\n\n**Example**\n\n| Time  | Description | Instance 1 | Instance 2 |\n| :---: | :--- | :--- | :--- |\n| t1 | Set the same key to an object or an array | JSON.SET doc $.a '{}' | JSON.SET doc $.a '[]' |\n| t2 | Add data to the object and array | <nobr>JSON.SET doc  $.a.x '\"y\"'</nobr> <br /><br /> Result: <br /> {\"a\": {\"x\": \"y\"}} | <nobr>JSON.SET doc $.a '[\"z\"]'</nobr> <br /><br /> Result: <br /> {\"a\": [\"z\"]} |\n| t3 | Active-Active synchronization | – Sync – | – Sync – |\n| t4 | Instance 1 wins | JSON.GET doc $ <br /><br /> Result: <br /> {\"a\": {\"x\": \"y\"}} | JSON.GET doc $ <br /><br /> Result: <br /> {\"a\": {\"x\": \"y\"}} |"
    },
    {
      "id": "create-versus-create",
      "title": "Create versus create",
      "role": "content",
      "text": "**Conflict**\n\nTwo instances concurrently use `JSON.SET` to assign a new JSON document to the same key.\n\n**Resolution type**\n\nWin over\n\n**Resolution rule**\n\nThe instance with the smaller ID wins.\n\n**Example**\n\n| Time  | Description | Instance 1 | Instance 2 |\n| :---: | :--- | :--- | :--- |\n| t1 | Create a new JSON document | <nobr>JSON.SET doc $ '{\"field\": \"a\"}'</nobr> | <nobr>JSON.SET doc $ '{\"field\": \"b\"}'</nobr> |\n| t2 | Active-Active synchronization | – Sync – | – Sync – |\n| t3 | Instance 1 wins | JSON.GET doc $ <br /><br /> Result: <br /> {\"field\": \"a\"} | JSON.GET doc $ <br /><br /> Result: <br /> {\"field\": \"a\"} |"
    },
    {
      "id": "create-versus-update",
      "title": "Create versus update",
      "role": "content",
      "text": "**Conflict**\n\nInstance 1 creates a new document and assigns it to an existing key with `JSON.SET`.\n\nInstance 2 updates the existing content of the same key with `JSON.SET`.\n\n**Resolution type**\n\nWin over\n\n**Resolution rule**\n\nThe operation that creates a new document wins.\n\n**Example**\n\n| Time  | Description | Instance 1 | Instance 2 |\n| :---: | :--- | :--- | :--- |\n| t1 | The document exists on both instances | JSON.GET doc $ <br /><br /> Result: <br />  {\"field1\": \"value1\"} | JSON.GET doc $ <br /><br /> Result: <br />  {\"field1\": \"value1\"} |\n| t2 | Instance 1 creates a new document; instance 2 updates the existing document | <nobr>JSON.SET doc $ '{\"field2\": \"value2\"}'</nobr> | <nobr>JSON.SET doc $.field1 '[1, 2, 3]'</nobr> |\n| t3 | Active-Active synchronization | – Sync – | – Sync – |\n| t4 | Instance 1 wins | JSON.GET doc . <br /><br /> Result: <br /> {\"field2\": \"value2\"} | JSON.GET doc . <br /><br /> Result: <br /> {\"field2\": \"value2\"} |"
    },
    {
      "id": "delete-versus-create",
      "title": "Delete versus create",
      "role": "content",
      "text": "**Conflict**\n\nInstance 1 deletes a JSON document with `JSON.DEL`.\n\nInstance 2 uses `JSON.SET` to create a new JSON document and assign it to the key deleted by instance 1.\n\n**Resolution type**\n\nWin over\n\n**Resolution rule**\n\nDocument creation wins over deletion.\n\n**Example**\n\n| Time  | Description | Instance 1 | Instance 2 |\n| :---: | :--- | :--- | :--- |\n| t1 | The document exists on both instances | JSON.GET doc $ <br /><br /> Result: <br /> {\"field1\": \"value1\"} | JSON.GET doc $ <br /><br /> Result: <br /> {\"field1\": \"value1\"} |\n| t2 | Instance 1 deletes the document; instance 2 creates a new document | JSON.DEL doc | <nobr>JSON.SET doc $ '{\"field1\": \"value2\"}'</nobr> |\n| t3 | Active-Active synchronization | – Sync – | – Sync – |\n| t4 | Instance 2 wins | JSON.GET doc $ <br /><br /> Result: <br /> <nobr>{\"field1\": \"value2\"}</nobr> | JSON.GET doc $ <br /><br /> Result: <br /> {\"field1\": \"value2\"} |"
    },
    {
      "id": "delete-versus-update",
      "title": "Delete versus update",
      "role": "content",
      "text": "**Conflict**\n\nInstance 1 deletes a JSON document with `JSON.DEL`.\n\nInstance 2 updates the content of the same document with `JSON.SET`.\n\n**Resolution type**\n\nWin over\n\n**Resolution rule**\n\nDocument deletion wins over updates.\n\n**Example**\n\n| Time  | Description | Instance 1 | Instance 2 |\n| :---: | :--- | :--- | :--- |\n| t1 | The document exists on both instances | JSON.GET doc $ <br /><br /> Result: <br /> <nobr>{\"field1\": \"value1\"}</nobr> | JSON.GET doc $ <br /><br /> Result: <br /> {\"field1\": \"value1\"} |\n| t2 | Instance 1 deletes the document; instance 2 updates it | JSON.DEL doc | <nobr>JSON.SET doc $.field1 '[1, 2, 3]'</nobr> |\n| t3 | Active-Active synchronization | – Sync – | – Sync – |\n| t4 | Instance 1 wins | JSON.GET doc $ <br /><br /> Result: <br /> (nil) | JSON.GET doc $ <br /><br /> Result: <br /> (nil) |"
    },
    {
      "id": "update-versus-update",
      "title": "Update versus update",
      "role": "content",
      "text": "**Conflict**\n\nInstance 1 updates a field inside a JSON document with `JSON.SET`.\n\nInstance 2 updates the same field with a different value.\n\n**Resolution type**\n\nWin over\n\n**Resolution rule**\n\nThe instance with the smallest ID wins.\n\n**Example**\n\n| Time  | Description | Instance 1 | Instance 2 |\n| :---: | :--- | :--- | :--- |\n| t1 | The document exists on both instances | JSON.GET doc $ <br /><br /> Result: <br /> {\"field\": \"a\"} | JSON.GET doc $ <br /><br /> Result: <br /> {\"field\": \"a\"} |\n| t2 | Update the same field with different data | <nobr>JSON.SET doc $.field \"b\"</nobr> | <nobr>JSON.SET doc $.field \"c\"</nobr> |\n| t3 | Active-Active synchronization | – Sync – | – Sync – |\n| t4 | Instance 1 wins | JSON.GET doc $ <br /><br /> Result: <br /> {\"field\": \"b\"} | JSON.GET doc $ <br /><br /> Result: <br /> {\"field\": \"b\"} |"
    },
    {
      "id": "update-versus-clear",
      "title": "Update versus clear",
      "role": "content",
      "text": "The version of RedisJSON prior to v2.2 has two different ways to reset the content of a JSON object:\n\n- Assign a new empty JSON object:\n    \n    [code example]\n\n    If you use this method, it cannot be merged with a concurrent update.\n\n- For each key, remove it with `JSON.DEL`:\n\n    [code example]\n\n    With this method, it can merge the reset with concurrent updates.\n\nAs of RedisJSON v2.2, you can use the `JSON.CLEAR` command to reset the JSON document without removing each key manually. This method also lets concurrent updates be merged.\n\n#### Assign an empty object\n\n**Conflict**\n\nInstance 1 adds \"red\" to the existing \"colors\" object with `JSON.SET`.\n\nInstance 2 assigns a new empty object for \"colors\".\n\n**Resolution type**\n\nWin over\n\n**Resolution rule**\n\nDocument creation wins over the update, so the result will be an empty object.\n\n**Example**\n\n| Time  | Description | Instance 1 | Instance 2 |\n| :---: | :--- | :--- | :--- |\n| t1 | The document exists on both instances | JSON.GET doc $ <br /><br /> Result: <br /> {\"colors\": {\"blue\": \"#0000ff\"}} | JSON.GET doc $ <br /><br /> Result: <br /> {\"colors\": {\"blue\": \"#0000ff\"}} |\n| t2 | Instance 1 adds a new color; instance 2 resets colors to an empty object | <nobr>JSON.SET doc $.colors.red ‘#ff0000’</nobr> | JSON.SET doc $.colors ‘{}’ |\n| t3 | Instance 2 adds a new color |  | <nobr>JSON.SET doc $.colors.green ‘#00ff00’</nobr> |\n| t4 |  | JSON.GET doc $ <br /><br /> Result: <br /> {\"colors\": {\"blue\": \"#0000ff\", \"red\": \"#ff0000\"}} | JSON.GET doc $ <br /><br /> Result: <br /> {\"colors\": {\"green\": \"#00ff00\"}} |\n| t5 | Active-Active synchronization | – Sync – | – Sync – |\n| t6 | Instance 2 wins | JSON.GET doc $ <br /><br /> Result: <br /> {\"colors\": {\"green\": \"#00ff00\"}} | JSON.GET doc $ <br /><br /> Result: <br /> {\"colors\": {\"green\": \"#00ff00\"}} |\n\n#### Use `JSON.CLEAR`\n\n**Conflict**\n\nInstance 1 adds \"red\" to the existing \"colors\" object with `JSON.SET`.\n\nInstance 2 clears the \"colors\" object with `JSON.CLEAR` and adds \"green\" to \"colors\".\n\n**Resolution type**\n\nMerge\n\n**Resolution rule**\n\nMerges the results of all operations.\n\n**Example**\n\n| Time  | Description | Instance 1 | Instance 2 |\n| :---: | :--- | :--- | :--- |\n| t1 | The document exists on both instances | JSON.GET doc $ <br /><br /> Result: <br /> {\"colors\": {\"blue\": \"#0000ff\"}} | JSON.GET doc $ <br /><br /> Result: <br /> {\"colors\": {\"blue\": \"#0000ff\"}} |\n| t2 | Instance 1 adds a new color; instance 2 resets the colors | <nobr>JSON.SET doc $.colors.red ‘#ff0000’</nobr> | JSON.CLEAR doc $.colors |\n| t3 |  | JSON.GET doc $ <br /><br /> Result: <br /> {\"colors\": {\"blue\": \"#0000ff\", \"red\": \"#ff0000\"}} | JSON.GET doc $ <br /><br /> Result: <br /> {\"colors\": {}} |\n| t4 | Instance 2 adds a new color |  | <nobr>JSON.SET doc $.colors.green ‘#00ff00’</nobr> |\n| t5 |  |  | JSON.GET doc $ <br /><br /> Result: <br /> {\"colors\": {\"green\": \"#00ff00\"}} |\n| t6 | Active-Active synchronization | – Sync – | – Sync – |\n| t7 | Merges the results of both instances | JSON.GET doc $ <br /><br /> Result: <br /> {\"colors\": {\"red\": \"#ff0000\", \"green\": \"#00ff00\"}} | JSON.GET doc $ <br /><br /> Result: <br /> {\"colors\": {\"red\": \"#ff0000\", \"green\": \"#00ff00\"}} |"
    },
    {
      "id": "update-versus-update-array",
      "title": "Update versus update array",
      "role": "content",
      "text": "**Conflict**\n\nTwo instances update the same existing array with different content.\n\n**Resolution type**\n\nMerge\n\n**Resolution rule**\n\nMerges the results of all operations on the array. Preserves the original element order from each instance.\n\n**Example**\n\n| Time  | Description | Instance 1 | Instance 2 |\n| :---: | :--- | :--- | :--- |\n| t1 | The document exists on both instances | JSON.GET doc $ <br /><br /> Result: <br /> '[\"a\", \"b\", \"c\"]' | JSON.GET doc $ <br /><br /> Result: <br /> '[\"a\", \"b\", \"c\"]' |\n| t2 | Instance 1 removes an array element; instance 2 adds one | JSON.ARRPOP doc $ 1 <br /><br /> Result: <br /> [\"a\", \"c\"] | <nobr>JSON.ARRINSERT doc $ 0 ‘\"y\"’</nobr> <br /><br /> Result: <br /> [\"y\", \"a\", \"b\", \"c\"] |\n| t3 | Both instances add another element to the array | <nobr>JSON.ARRINSERT doc $ 1 ‘\"x\"’</nobr> <br /><br /> Result: <br /> [\"a\", \"x\", \"c\"] | <nobr>JSON.ARRINSERT doc $ 2 ‘\"z\"’</nobr> <br /><br /> Result: <br /> [\"y\", \"a\", \"z\", \"b\", \"c\"] |\n| t4 | Active-Active synchronization | – Sync – | – Sync – |\n| t5 | Merge results from both instances | JSON.GET doc $ <br /><br /> Result: <br /> [\"y\", \"a\", \"x\", \"z\", \"c\"] | JSON.GET doc $ <br /><br /> Result: <br /> [\"y\", \"a\", \"x\", \"z\", \"c\"] |"
    },
    {
      "id": "update-versus-delete-array-element",
      "title": "Update versus delete array element",
      "role": "content",
      "text": "**Conflict**\n\nInstance 1 removes an element from a JSON array with `JSON.ARRPOP`.\n\nInstance 2 updates the same element that instance 1 removes.\n\n**Resolution type**\n\nWin over\n\n**Resolution rule**\n\nDeletion wins over updates.\n\n**Example**\n\n| Time  | Description | Instance 1 | Instance 2 |\n| :---: | :--- | :--- | :--- |\n| t1 | The document exists on both instances | JSON.GET doc $ <br /><br /> Result: <br /> {\"todo\": [{\"title\": \"buy milk\", \"done\": false}]} | JSON.GET doc $ <br /><br /> Result: <br /> {\"todo\": [{\"title\": \"buy milk\", \"done\": false}]} |\n| t2 | Instance 1 removes an array element; instance 2 updates the same element | <nobr>JSON.ARRPOP doc $.todo 0</nobr> | <nobr>JSON.SET doc '$.todo[0][\"done\"]' 'true'’</nobr> |\n| t3 |  | JSON.GET doc $ <br /><br /> Result: <br /> {\"todo\": []} | JSON.GET doc $ <br /><br /> Result: <br /> [{\"title\": \"buy milk\", \"done\": true}]} |\n| t4 | Active-Active synchronization | – Sync – | – Sync – |\n| t5 | Instance 1 wins | JSON.GET doc $ <br /><br /> Result: <br /> doc = {\"todo\": []} | JSON.GET doc $ <br /><br /> Result: <br /> doc = {\"todo\": []} |"
    },
    {
      "id": "update-versus-update-object",
      "title": "Update versus update object",
      "role": "content",
      "text": "**Conflict**\n\nBoth instances update the same existing object with different content.\n\n**Resolution type**\n\nMerge\n\n**Resolution rule**\n\nMerges the results of all operations on the object.\n\n**Example**\n\n| Time  | Description | Instance 1 | Instance 2 |\n| :---: | :--- | :--- | :--- |\n| t1 | The document exists on both instances | JSON.GET doc $ <br /><br /> Result: <br /> '{\"grocery\": []}' | JSON.GET doc $ <br /><br /> Result: <br /> '{\"grocery\": []}' |\n| t2 | Add new elements to the array | <nobr>JSON.ARRAPPEND doc $.grocery ‘\"eggs\"’</nobr> | JSON.ARRAPPEND doc $.grocery ‘\"milk\"’ |\n| t3 | Add new elements to the array | JSON.ARRAPPEND doc $.grocery ‘\"ham\"’ | <nobr>JSON.ARRAPPEND doc $.grocery ‘\"flour\"’</nobr> |\n| t4 |  | JSON.GET doc $ <br /><br /> Result: <br /> {\"grocery\":[\"eggs\", \"ham\"]} | JSON.GET doc $ <br /><br /> Result: <br /> {\"grocery\":[\"milk\", \"flour\"]} |\n| t5 | Active-Active synchronization | – Sync – | – Sync – |\n| t6 | Merges the results from both instances | JSON.GET doc . <br /><br /> Result: <br /> {\"grocery\":[\"eggs\",\"ham\",\"milk\", \"flour\"]} | JSON.GET doc . <br /><br /> Result: <br /> {\"grocery\":[\"eggs\",\"ham\",\"milk\", \"flour\" ]} |"
    }
  ],
  "examples": [
    {
      "id": "update-versus-clear-ex0",
      "language": "sh",
      "code": "JSON.SET doc $.colors '{}'",
      "section_id": "update-versus-clear"
    },
    {
      "id": "update-versus-clear-ex1",
      "language": "sh",
      "code": "JSON.DEL doc $.colors.blue",
      "section_id": "update-versus-clear"
    }
  ]
}
