{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "relate changelog",
  "home_page_url": "https://relatedb.ai/docs/reference/changelog/",
  "feed_url": "https://relatedb.ai/docs/changelog.json",
  "description": "relate, the embedded Cypher graph database (relatedb.ai): what each release added, changed, deprecated, removed and fixed, newest first.",
  "language": "en-US",
  "_relate": {
    "verified": "0.1.2",
    "markdown_url": "https://relatedb.ai/docs/reference/changelog.md",
    "deprecation_policy": [
      "relate is pre-1.0. Its releases follow semantic versioning, under which anything can change in a 0.x release, a patch release included: 0.16.1 removed the `apoc.coll.sort` spelling and replaced the C ABI with an incompatible typed one.",
      "A change that can make working code or statements fail is marked **Breaking** in the entry of the release that ships it, under Changed or Removed, with its replacement when there is one. A feature that still works but is to be removed is listed under Deprecated in the release that deprecates it."
    ]
  },
  "items": [
    {
      "id": "https://relatedb.ai/docs/reference/changelog/#0.1.2",
      "url": "https://relatedb.ai/docs/reference/changelog/#0.1.2",
      "title": "relate 0.1.2",
      "date_published": "2026-11-09T22:07:38Z",
      "content_text": "## 0.1.2\n\nReleased 2026-11-09. Changes since 0.1.1.\n\nElement ids carry the database's name, and a shortest path between two endpoints matched by property maps is searched from both ends.\n\n### Changed\n\n- **Breaking.** `elementId()` names the database: the first node of the default database is `4:relate-neo4j:n0` and its first relationship `5:relate-neo4j:r0`, where 0.1.1 returned `4:relate:n0` and `5:relate:r0`, and the clients, JSON output and Bolt carry the same strings. See [Types and values](https://relatedb.ai/docs/reference/cypher/types-and-values/), [Functions](https://relatedb.ai/docs/reference/cypher/functions/).\n- A `shortestPath` whose two endpoints are matched by property maps looks up both endpoints and searches from both ends at once.\n- Opening a store whose write-ahead log replays nothing no longer rebuilds its indexes.\n- `relate upgrade` no longer prints the notice of the rename after its status line.",
      "_relate": {
        "version": "0.1.2",
        "date": "2026-11-09",
        "previous": "0.1.1",
        "since_url": "https://relatedb.ai/docs/reference/changelog/#since-0.1.1",
        "summary": "Element ids carry the database's name, and a shortest path between two endpoints matched by property maps is searched from both ends.",
        "changed": [
          {
            "text": "`elementId()` names the database: the first node of the default database is `4:relate-neo4j:n0` and its first relationship `5:relate-neo4j:r0`, where 0.1.1 returned `4:relate:n0` and `5:relate:r0`, and the clients, JSON output and Bolt carry the same strings.",
            "breaking": true,
            "pages": [
              {
                "id": "reference/cypher/types-and-values",
                "url": "https://relatedb.ai/docs/reference/cypher/types-and-values/"
              },
              {
                "id": "reference/cypher/functions",
                "url": "https://relatedb.ai/docs/reference/cypher/functions/"
              }
            ]
          },
          {
            "text": "A `shortestPath` whose two endpoints are matched by property maps looks up both endpoints and searches from both ends at once.",
            "breaking": false,
            "pages": []
          },
          {
            "text": "Opening a store whose write-ahead log replays nothing no longer rebuilds its indexes.",
            "breaking": false,
            "pages": []
          },
          {
            "text": "`relate upgrade` no longer prints the notice of the rename after its status line.",
            "breaking": false,
            "pages": []
          }
        ]
      }
    },
    {
      "id": "https://relatedb.ai/docs/reference/changelog/#0.1.1",
      "url": "https://relatedb.ai/docs/reference/changelog/#0.1.1",
      "title": "relate 0.1.1",
      "date_published": "2026-11-09T20:25:16Z",
      "content_text": "## 0.1.1\n\nReleased 2026-11-09. Changes since 0.1.0.\n\nFull-text search reads the index's query syntax and ranks by BM25, and the Parquet codec can store each promoted property in a column of its own.\n\n### Added\n\n- `--snapshot-format parquet-wide`, on a query run and on `relate serve`, which gains the flag: the Parquet codec writes one typed column per promoted property key, and from the store's next checkpoint on every later open keeps it wide. See [Storage formats](https://relatedb.ai/docs/reference/storage/formats/), [CLI flags](https://relatedb.ai/docs/reference/cli/flags/).\n- Full-text search pages with `SKIP` and `OFFSET`, and `WITH ANALYZER` is evaluated per row, English stemming included.\n\n### Changed\n\n- **Breaking.** Full-text search passes the query string to the index's query syntax, so `AND` and `NOT` are operators while a lowercase `and` stays a term, and it ranks hits by BM25 scores, so a hit's `score` and the order of hits can differ from 0.1.0. See [Full-text and hybrid search](https://relatedb.ai/docs/guides/cypher/full-text-and-hybrid-search/), [Search](https://relatedb.ai/docs/reference/cypher/search/).\n- **Breaking.** The Java client's `QueryType`, `Namespace`, `Severity` and `Category` are enums instead of strings, and `PlanActual` carries the whole plan shape. See [Java API](https://relatedb.ai/docs/reference/api/java/).\n- POINT indexes seek radius and bounding-box queries through an R*-tree.\n- The variable-shadowing notification also looks inside the bodies of `EXISTS`, `COUNT` and `COLLECT` subqueries.\n\n### Fixed\n\n- `round()` on a decimal, the sort order of temporal values, and the type of a nested list whose elements have mixed types.\n- A list value at a `WHERE` or `FILTER` position is coerced to a predicate.\n- `FINISH` is accepted after a catalog command that returns rows, and a schema command runs only as a statement of its own.",
      "_relate": {
        "version": "0.1.1",
        "date": "2026-11-09",
        "previous": "0.1.0",
        "since_url": "https://relatedb.ai/docs/reference/changelog/#since-0.1.0",
        "summary": "Full-text search reads the index's query syntax and ranks by BM25, and the Parquet codec can store each promoted property in a column of its own.",
        "added": [
          {
            "text": "`--snapshot-format parquet-wide`, on a query run and on `relate serve`, which gains the flag: the Parquet codec writes one typed column per promoted property key, and from the store's next checkpoint on every later open keeps it wide.",
            "breaking": false,
            "pages": [
              {
                "id": "reference/storage/formats",
                "url": "https://relatedb.ai/docs/reference/storage/formats/"
              },
              {
                "id": "reference/cli/flags",
                "url": "https://relatedb.ai/docs/reference/cli/flags/"
              }
            ]
          },
          {
            "text": "Full-text search pages with `SKIP` and `OFFSET`, and `WITH ANALYZER` is evaluated per row, English stemming included.",
            "breaking": false,
            "pages": []
          }
        ],
        "changed": [
          {
            "text": "Full-text search passes the query string to the index's query syntax, so `AND` and `NOT` are operators while a lowercase `and` stays a term, and it ranks hits by BM25 scores, so a hit's `score` and the order of hits can differ from 0.1.0.",
            "breaking": true,
            "pages": [
              {
                "id": "guides/cypher/full-text-and-hybrid-search",
                "url": "https://relatedb.ai/docs/guides/cypher/full-text-and-hybrid-search/"
              },
              {
                "id": "reference/cypher/search",
                "url": "https://relatedb.ai/docs/reference/cypher/search/"
              }
            ]
          },
          {
            "text": "The Java client's `QueryType`, `Namespace`, `Severity` and `Category` are enums instead of strings, and `PlanActual` carries the whole plan shape.",
            "breaking": true,
            "pages": [
              {
                "id": "reference/api/java",
                "url": "https://relatedb.ai/docs/reference/api/java/"
              }
            ]
          },
          {
            "text": "POINT indexes seek radius and bounding-box queries through an R*-tree.",
            "breaking": false,
            "pages": []
          },
          {
            "text": "The variable-shadowing notification also looks inside the bodies of `EXISTS`, `COUNT` and `COLLECT` subqueries.",
            "breaking": false,
            "pages": []
          }
        ],
        "fixed": [
          {
            "text": "`round()` on a decimal, the sort order of temporal values, and the type of a nested list whose elements have mixed types.",
            "breaking": false,
            "pages": []
          },
          {
            "text": "A list value at a `WHERE` or `FILTER` position is coerced to a predicate.",
            "breaking": false,
            "pages": []
          },
          {
            "text": "`FINISH` is accepted after a catalog command that returns rows, and a schema command runs only as a statement of its own.",
            "breaking": false,
            "pages": []
          }
        ]
      }
    },
    {
      "id": "https://relatedb.ai/docs/reference/changelog/#0.1.0",
      "url": "https://relatedb.ai/docs/reference/changelog/#0.1.0",
      "title": "relate 0.1.0",
      "date_published": "2026-11-09T13:44:01Z",
      "content_text": "## 0.1.0\n\nReleased 2026-11-09. Changes since 0.16.1.\n\nThe first release published as relate, which restarts the version line at 0.1.0 after cypherlite's 0.16.1: the release assets are `relate-<os>-<arch>` and `relate-ffi-<target>.tar.gz`, and the signer and the signature namespace are `relate-release`, with the same key.\n\n### Added\n\n- Every machine-readable result carries per-phase timings and the plan cache's outcome: `--mode envelope` and `--mode json` add a `timings` object and `planCache`, `--mode jsonl` ends each statement with a line holding both, `--mode toon` ends with `timings:` and `planCache:` entries, the envelope of MCP and the WebAssembly build adds `lex_parse_ms`, `rewrite_ms`, `lower_ms`, `result_generation_ms` and `plan_cache`, and the Rust crate's `QueryResult` adds the same four timings and `plan_cache()`; the C ABI and the other clients expose none of them yet. See [Output modes](https://relatedb.ai/docs/reference/cli/output-modes/).\n- The `FOR` clause runs without a preview gate.\n\n### Changed\n\n- **Breaking.** `--mode json` prints an object for every statement, `{\"data\": [...], \"planCache\": ..., \"timings\": {...}}`, where 0.16.1 printed a bare array for a result the row cap did not cut. See [Output modes](https://relatedb.ai/docs/reference/cli/output-modes/).\n- **Breaking.** `--mode jsonl` prints one more line per statement, its timings, so a statement with no rows prints that one line instead of nothing. See [Output modes](https://relatedb.ai/docs/reference/cli/output-modes/).\n- **Breaking.** `relate clone` refuses a `markdown` store as the source of a `.rl` bundle unless `--to-snapshot-format` names `parquet` or `json`, with `Failed to clone database: semantic error: markdown body properties are set but the store's snapshot codec is parquet, not markdown; the configuration would be ignored`. See [relate clone](https://relatedb.ai/docs/reference/cli/clone/).\n- Usage metrics are written to a local spool at exit and sent by the next run, so an exit never waits on the network, and `RELATE_TELEMETRY_FLUSH_MS` is removed; `relate telemetry off` deletes the spool. See [Privacy and telemetry](https://relatedb.ai/docs/reference/privacy-and-telemetry/).\n\n### Fixed\n\n- `coll.max()` returns null when the list holds a null, as Neo4j does.\n- `toString()` of a path and an index into a null string return what Neo4j returns.\n- A count-style aggregate over a repeated node variable counts only self-loops.\n- In the Swift client, `transaction(_:)` rolls back when `commit()` throws.",
      "_relate": {
        "version": "0.1.0",
        "date": "2026-11-09",
        "previous": "0.16.1",
        "since_url": "https://relatedb.ai/docs/reference/changelog/#since-0.16.1",
        "summary": "The first release published as relate, which restarts the version line at 0.1.0 after cypherlite's 0.16.1: the release assets are `relate-<os>-<arch>` and `relate-ffi-<target>.tar.gz`, and the signer and the signature namespace are `relate-release`, with the same key.",
        "added": [
          {
            "text": "Every machine-readable result carries per-phase timings and the plan cache's outcome: `--mode envelope` and `--mode json` add a `timings` object and `planCache`, `--mode jsonl` ends each statement with a line holding both, `--mode toon` ends with `timings:` and `planCache:` entries, the envelope of MCP and the WebAssembly build adds `lex_parse_ms`, `rewrite_ms`, `lower_ms`, `result_generation_ms` and `plan_cache`, and the Rust crate's `QueryResult` adds the same four timings and `plan_cache()`; the C ABI and the other clients expose none of them yet.",
            "breaking": false,
            "pages": [
              {
                "id": "reference/cli/output-modes",
                "url": "https://relatedb.ai/docs/reference/cli/output-modes/"
              }
            ]
          },
          {
            "text": "The `FOR` clause runs without a preview gate.",
            "breaking": false,
            "pages": []
          }
        ],
        "changed": [
          {
            "text": "`--mode json` prints an object for every statement, `{\"data\": [...], \"planCache\": ..., \"timings\": {...}}`, where 0.16.1 printed a bare array for a result the row cap did not cut.",
            "breaking": true,
            "pages": [
              {
                "id": "reference/cli/output-modes",
                "url": "https://relatedb.ai/docs/reference/cli/output-modes/"
              }
            ]
          },
          {
            "text": "`--mode jsonl` prints one more line per statement, its timings, so a statement with no rows prints that one line instead of nothing.",
            "breaking": true,
            "pages": [
              {
                "id": "reference/cli/output-modes",
                "url": "https://relatedb.ai/docs/reference/cli/output-modes/"
              }
            ]
          },
          {
            "text": "`relate clone` refuses a `markdown` store as the source of a `.rl` bundle unless `--to-snapshot-format` names `parquet` or `json`, with `Failed to clone database: semantic error: markdown body properties are set but the store's snapshot codec is parquet, not markdown; the configuration would be ignored`.",
            "breaking": true,
            "pages": [
              {
                "id": "reference/cli/clone",
                "url": "https://relatedb.ai/docs/reference/cli/clone/"
              }
            ]
          },
          {
            "text": "Usage metrics are written to a local spool at exit and sent by the next run, so an exit never waits on the network, and `RELATE_TELEMETRY_FLUSH_MS` is removed; `relate telemetry off` deletes the spool.",
            "breaking": false,
            "pages": [
              {
                "id": "reference/privacy-and-telemetry",
                "url": "https://relatedb.ai/docs/reference/privacy-and-telemetry/"
              }
            ]
          }
        ],
        "fixed": [
          {
            "text": "`coll.max()` returns null when the list holds a null, as Neo4j does.",
            "breaking": false,
            "pages": []
          },
          {
            "text": "`toString()` of a path and an index into a null string return what Neo4j returns.",
            "breaking": false,
            "pages": []
          },
          {
            "text": "A count-style aggregate over a repeated node variable counts only self-loops.",
            "breaking": false,
            "pages": []
          },
          {
            "text": "In the Swift client, `transaction(_:)` rolls back when `commit()` throws.",
            "breaking": false,
            "pages": []
          }
        ]
      }
    },
    {
      "id": "https://relatedb.ai/docs/reference/changelog/#0.16.1",
      "url": "https://relatedb.ai/docs/reference/changelog/#0.16.1",
      "title": "relate 0.16.1",
      "date_published": "2026-11-04T17:26:42Z",
      "content_text": "## 0.16.1\n\nReleased 2026-11-04. Changes since 0.16.0.\n\nThe last release published under the name cypherlite: its release assets carry that name, and a successful `cypherlite upgrade` ends with a notice of the rename and the relate install command.\n\n### Changed\n\n- **Breaking.** The C ABI is the typed ABI v2: `relate_abi_version()` returns 2, values are read through typed accessors instead of JSON strings, parameters are passed through a typed builder instead of a JSON string, and an error arrives as one object with `code`, `gql_status`, `stage`, `retryable` and `message`.\n- The Python binding and the Java, JavaScript, Go and Swift clients use the typed ABI v2.\n- The typed parameter builder is bounded: at most 100,000 entries per container, 4 KiB per name, and 16 MiB in all.\n- A bookmark carries the engine's commit sequence, through the C ABI, Python and Bolt.\n- An error of the internal class crosses the C ABI with a generic message; the internal detail stays inside the engine.\n- **Breaking.** A non-boolean value where Cypher requires a boolean, such as a quantifier's `WHERE` or an operand of `AND`, `OR` or `XOR`, fails with `InvalidArgumentType` instead of a generic syntax error.\n- **Breaking.** A clause that reads an entity it creates fails with `Entity, '<name>', cannot be created and referenced in the same clause`, and a `CREATE` or `MERGE` whose node is bound to null fails instead of creating a new node.\n- **Breaking.** An administration command with a `USE` clause that names a graph other than `system` fails with `UseClauseWithAdministrationCommand`. See [Errors](https://relatedb.ai/docs/reference/errors/#engine-use-on-administration-command).\n\n### Removed\n\n- **Breaking.** The `apoc.coll.sort` spelling: a call fails as an unknown function, `UnknownFunction: unknown function apoc.coll.sort()`, and `coll.sort` is the replacement. See [Errors](https://relatedb.ai/docs/reference/errors/#engine-unknown-function).\n\n### Fixed\n\n- A frontier search that exhausts its re-arrival budget falls back to the plain walk instead of dropping endpoints, which could make `count(DISTINCT n)` return 0 on a dense clique.\n- `push` keeps a node's secondary labels and merges on its keyed label, so an update no longer creates a second node.",
      "_relate": {
        "version": "0.16.1",
        "date": "2026-11-04",
        "previous": "0.16.0",
        "since_url": "https://relatedb.ai/docs/reference/changelog/#since-0.16.0",
        "summary": "The last release published under the name cypherlite: its release assets carry that name, and a successful `cypherlite upgrade` ends with a notice of the rename and the relate install command.",
        "changed": [
          {
            "text": "The C ABI is the typed ABI v2: `relate_abi_version()` returns 2, values are read through typed accessors instead of JSON strings, parameters are passed through a typed builder instead of a JSON string, and an error arrives as one object with `code`, `gql_status`, `stage`, `retryable` and `message`.",
            "breaking": true,
            "pages": []
          },
          {
            "text": "The Python binding and the Java, JavaScript, Go and Swift clients use the typed ABI v2.",
            "breaking": false,
            "pages": []
          },
          {
            "text": "The typed parameter builder is bounded: at most 100,000 entries per container, 4 KiB per name, and 16 MiB in all.",
            "breaking": false,
            "pages": []
          },
          {
            "text": "A bookmark carries the engine's commit sequence, through the C ABI, Python and Bolt.",
            "breaking": false,
            "pages": []
          },
          {
            "text": "An error of the internal class crosses the C ABI with a generic message; the internal detail stays inside the engine.",
            "breaking": false,
            "pages": []
          },
          {
            "text": "A non-boolean value where Cypher requires a boolean, such as a quantifier's `WHERE` or an operand of `AND`, `OR` or `XOR`, fails with `InvalidArgumentType` instead of a generic syntax error.",
            "breaking": true,
            "pages": []
          },
          {
            "text": "A clause that reads an entity it creates fails with `Entity, '<name>', cannot be created and referenced in the same clause`, and a `CREATE` or `MERGE` whose node is bound to null fails instead of creating a new node.",
            "breaking": true,
            "pages": []
          },
          {
            "text": "An administration command with a `USE` clause that names a graph other than `system` fails with `UseClauseWithAdministrationCommand`.",
            "breaking": true,
            "pages": [
              {
                "id": "reference/errors#engine-use-on-administration-command",
                "url": "https://relatedb.ai/docs/reference/errors/#engine-use-on-administration-command"
              }
            ]
          }
        ],
        "removed": [
          {
            "text": "The `apoc.coll.sort` spelling: a call fails as an unknown function, `UnknownFunction: unknown function apoc.coll.sort()`, and `coll.sort` is the replacement.",
            "breaking": true,
            "pages": [
              {
                "id": "reference/errors#engine-unknown-function",
                "url": "https://relatedb.ai/docs/reference/errors/#engine-unknown-function"
              }
            ]
          }
        ],
        "fixed": [
          {
            "text": "A frontier search that exhausts its re-arrival budget falls back to the plain walk instead of dropping endpoints, which could make `count(DISTINCT n)` return 0 on a dense clique.",
            "breaking": false,
            "pages": []
          },
          {
            "text": "`push` keeps a node's secondary labels and merges on its keyed label, so an update no longer creates a second node.",
            "breaking": false,
            "pages": []
          }
        ]
      }
    }
  ]
}
