Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
8256a0d
Add Memgraph v3.14.0 and Lab v3.14.0 release note titles
vpavicic Sep 15, 2026
64d32be
Merge branch 'main' into release/3.14
vpavicic Sep 15, 2026
f474980
docs: the bare pattern shorthand takes what a MATCH pattern takes (#1…
imilinovic Sep 15, 2026
4425c23
docs: document the nullIf built-in (#1763)
imilinovic Sep 15, 2026
4cf8c19
Add Memgraph v3.14.0 release notes and drop per-release sitemap steps.
vpavicic Sep 15, 2026
0c52c5f
Merge branch 'main' into release/3.14
vpavicic Sep 15, 2026
bda49f3
docs: unlisted auth schemes pass through on coordinators without SSO …
as51340 Oct 2, 2026
4930234
docs: document disk_available row in SHOW STORAGE INFO (#1791)
as51340 Oct 2, 2026
21588c6
docs: allow UNWIND in an EXISTS, COUNT or COLLECT body (#1783)
imilinovic Oct 2, 2026
4558990
docs: add collections.index_of (#1782)
imilinovic Oct 2, 2026
b6ac321
feat: label expressions in node patterns and expressions (#1797)
imilinovic Oct 2, 2026
1f7dfeb
Document OPTIONAL CALL subqueries (#1776)
imilinovic Oct 2, 2026
cf0083d
Complete the Memgraph v3.14.0 changelog.
vpavicic Oct 2, 2026
ae19312
Merge branch 'main' into release/3.14
vpavicic Oct 2, 2026
06472cf
Merge branch 'main' into release/3.14
katarinasupe Oct 7, 2026
935c180
Add v3.14.0 release notes for nine more PRs and tighten bug-fix skill…
vpavicic Oct 8, 2026
e2f6c97
Add v3.14.0 release notes for 18 more milestone PRs.
vpavicic Oct 13, 2026
cf48768
feat(dbms): close idle sessions that keep a FORCE-dropped database pi…
katarinasupe Oct 20, 2026
aeef794
How Memgraph compares and orders values (3.14 comparison series) (#1833)
katarinasupe Oct 20, 2026
d814c4d
docs: explain and raise the per-process open files limit (#1834)
andrejtonev Oct 20, 2026
4494e32
Document auth queries in explicit transactions (#1836)
colinbarry Oct 20, 2026
4ab3e1f
docs(multi-tenancy): what happens after DROP DATABASE ... FORCE (#1842)
andrejtonev Oct 20, 2026
ffdc47f
feat(query): tenant DB in SHOW TRANSACTIONS / SHOW ACTIVE USERS + for…
andrejtonev Oct 20, 2026
9cb75f0
docs: per-session state lasts for the connection; a user switch clear…
andrejtonev Oct 20, 2026
d8fae30
release notes 3.14: correct #4571 #4573 #4577 #4843 #4932; add #5029 …
andrejtonev Oct 20, 2026
0815f69
feat(query): SHOW/TERMINATE SESSIONS (#1814)
katarinasupe Oct 20, 2026
b70d3d4
Conditional subqueries with WHEN in CALL, EXISTS, COUNT and COLLECT (…
imilinovic Oct 20, 2026
924aa31
release notes 3.14: add #4524 #4953 #5026 #5032 #5107 #5111 #5126 #51…
vpavicic Oct 20, 2026
8db7bef
update docs for FIPS builds of Memgraph (#1848)
mattkjames7 Oct 20, 2026
7f042ae
Merge branch 'main' into release/3.14
vpavicic Oct 21, 2026
f80dfc9
docs: move WHEN in EXISTS, COUNT and COLLECT bodies to 3.15
katarinasupe Oct 21, 2026
7557061
docs: tag non-runnable examples and drop duplicate Previous releases …
katarinasupe Oct 21, 2026
4ec3ed0
release notes 3.14: #4969 closes only connections whose driver sessio…
katarinasupe Oct 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pages/advanced-algorithms/available-algorithms.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ Running `SHOW QUERY CALLABLE MAPPINGS` requires the `CONFIG` privilege.
| apoc.coll.unionAll | Returns the union of two input lists, including duplicates | [collections.union_all()](/advanced-algorithms/available-algorithms/collections#union_all) |
| apoc.coll.removeAll | Removes defined elements from the input list | [collections.remove_all()](/advanced-algorithms/available-algorithms/collections#remove_all) |
| apoc.coll.contains | Verifies the existence of an input value in an input list | [collections.contains()](/advanced-algorithms/available-algorithms/collections#contains) |
| apoc.coll.indexOf | Returns the position of the first element equal to a value | [collections.index_of()](/advanced-algorithms/available-algorithms/collections#index_of) |
| apoc.coll.flatten | Returns flattened list of inputs provided | [collections.flatten()](/advanced-algorithms/available-algorithms/collections#flatten) |
| apoc.coll.frequenciesAsMap | Returns a map of frequencies of the items in the collection | [collections.frequencies_as_map()](/advanced-algorithms/available-algorithms/collections#frequencies_as_map) |
| apoc.coll.pairs | Creates pairs of neighbor elements within an input list | [collections.pairs()](/advanced-algorithms/available-algorithms/collections#pairs) |
Expand Down
38 changes: 37 additions & 1 deletion pages/advanced-algorithms/available-algorithms/collections.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ argument-validation error. Each function returns a defined result:

| Function | Result when a list argument is `NULL` |
| --- | --- |
| `sum()`, `sum_longs()`, `avg()`, `min()`, `max()`, `to_set()`, `pairs()` | `null` |
| `sum()`, `sum_longs()`, `avg()`, `min()`, `max()`, `to_set()`, `pairs()`, `index_of()` | `null` |
| `union()`, `union_all()`, `disjunction()` | the other list; `null` when both are `NULL` |
| `remove_all()`, `subtract()` | `null` when the first list is `NULL`; the first list when the second is `NULL` |
| `intersection()`, `sort()`, `flatten()`, `duplicates()` | empty list `[]` |
Expand All @@ -58,6 +58,7 @@ argument-validation error. Each function returns a defined result:

- `min()` and `max()` skip `NULL` elements; a list containing only `NULL` values returns `null`.
- `contains()` and `contains_all()` never match a `NULL` search value (`NULL = NULL` is not true), so searching for `NULL` returns `false`.
- `index_of()` returns `null` for a `NULL` search value, and `-1` for a search value that holds a `NULL` at any depth (`NULL = x` is never true). A `NULL` list element matches nothing.
- `split()` treats a `NULL` delimiter as matching nothing and returns the whole list as a single part; `NULL` list elements are kept.
- `frequencies_as_map()` counts `NULL` elements under the `"NO_VALUE"` key.
- `flatten()`, `pairs()`, `to_set()`, `union()`, `union_all()`, `remove_all()`, `intersection()`, `disjunction()`, `subtract()` and `duplicates()` keep `NULL` elements as ordinary values.
Expand Down Expand Up @@ -281,6 +282,41 @@ RETURN collections.contains([1,2,3], "e") AS output;
+---------------------------------------------------------+
```

### `index_of()`

Returns the position of the first element in a list that is equal to an input
value, compared with `=`.

<Callout type="info">
This function is equivalent to Cypher's **coll.indexOf**.
</Callout>

{<h4 className="custom-header"> Input: </h4>}

- `coll: List[Any]` ➡ The input list searched for the value.
- `value: Any` ➡ The input value searched in the list.

{<h4 className="custom-header"> Output: </h4>}

- `integer` ➡ The zero-based position of the first element equal to `value`,
or `-1` if no element is.

{<h4 className="custom-header"> Usage: </h4>}

The following query will return the position of the first `5` in the list:

```cypher
RETURN collections.index_of([1, 5, 3, 5], 5) AS index;
```

```plaintext
+---------------------------------------------------------+
| index |
+---------------------------------------------------------+
| 1 |
+---------------------------------------------------------+
```

### `contains_all()`

Checks if a list contains all the values from another list.
Expand Down
2 changes: 1 addition & 1 deletion pages/client-libraries/java.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ public void createNode() {
```

The above code runs a simple query without any transaction management. It simplifies the experience, but you lose flexibility when running queries.
Since explicit transactions are multi-statement transactions, creating an index, constraints or auth config queries is not possible in multi-line transactions. Therefore, you need to use implicit transactions for those queries.
Since explicit transactions are multi-statement transactions, creating an index or constraints is not possible in multi-line transactions. Therefore, you need to use implicit transactions for those queries.

#### Asynchronous transaction management

Expand Down
97 changes: 64 additions & 33 deletions pages/clustering/high-availability/coordinator-authentication.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ carrying a coordinator privilege mask.
| Users | Stored in the auth store | Not supported |
| Roles | Stored in the auth store | Stored in the **Raft-replicated cluster state** |
| Privileges | Full privilege set + fine-grained access control | Exactly two: `COORDINATOR_READ`, `COORDINATOR_WRITE` |
| Basic auth | Username and password are validated | Passthrough — credentials are ignored (see [below](#basic-authentication-passthrough)) |
| Basic auth | Username and password are validated | Passthrough — credentials are ignored (see [below](#authentication-passthrough)) |
| Other Bolt schemes | Rejected unless mapped to an auth module | Passthrough, same as basic auth (see [below](#authentication-passthrough)) |
| SSO | Supported (OIDC, SAML, Kerberos) | Supported (OIDC, SAML, Kerberos) |

Because roles live in the Raft log, they survive coordinator restarts, are
Expand Down Expand Up @@ -110,57 +111,88 @@ Anything not recognized fails closed and requires `COORDINATOR_WRITE`.

## Authentication modes

A coordinator accepts exactly two kinds of Bolt connection: **basic/none** and
an **SSO scheme listed in `--auth-module-mappings`**. Any other scheme is
rejected with:
A coordinator sorts every Bolt connection into one of two paths based on the
authentication scheme the client sends:

```
The "<scheme>" authentication scheme isn't supported on this coordinator;
connect with basic auth or an SSO scheme listed in the auth-module-mappings flag.
```
- A scheme **listed in `--auth-module-mappings`** takes the [SSO
path](#sso-authentication): the coordinator runs the mapped auth module and
genuinely authenticates the connection.
- **Every other scheme** — `basic`, `none`, or a scheme that is **not** listed
in `--auth-module-mappings` — takes the [passthrough
path](#authentication-passthrough) described next.

There is no separate "unsupported scheme" rule. A client that keeps its
data-instance SSO configuration (for example, `oidc`) when talking to a
coordinator that has no SSO configured is treated exactly like a basic-auth
client.

### Basic authentication passthrough
### Authentication passthrough

When SSO is not in effect, connecting with a username and password (or with no
auth at all) **succeeds and the credentials are ignored**. The session gets full
When SSO is not in effect, connecting with a username and password, with no
auth at all, or with any scheme not listed in `--auth-module-mappings`
**succeeds and the credentials are ignored**. The session gets full
`COORDINATOR_WRITE` access. This is the pre-3.13 behavior, it requires no
license, and it keeps existing admin tooling working unchanged.

Basic/none authentication is **denied** only when **all three** of the following
hold:
<Callout type="info">
**Memgraph 3.13 rejected unlisted schemes.** In 3.13, a coordinator only let
`basic`/`none` through and refused any other scheme outright, so drivers that
sent their data-instance SSO scheme to a coordinator without SSO stopped
connecting after an upgrade from 3.12. From Memgraph 3.14, an unlisted scheme
follows the same passthrough rule as `basic`/`none`, restoring the 3.12
behavior.
</Callout>

Passthrough authentication is **denied** only when **all three** of the
following hold:

1. SSO is configured — `--auth-module-mappings` is non-empty.
2. The enterprise license is valid.
3. The committed role set contains at least one role holding
`COORDINATOR_WRITE`.

In that case the connection is rejected with:
In that case the connection is rejected. The message tells `basic`/`none` apart
from an unlisted scheme, because the remedy differs: the former needs an SSO
login, while the latter is usually a misspelled or unconfigured scheme.

For `basic`/`none`:

```
Basic authentication is disabled on this coordinator because SSO is configured;
connect with an SSO scheme listed in the auth-module-mappings flag.
```

For any other scheme not listed in `--auth-module-mappings`:

```
The "<scheme>" authentication scheme isn't supported on this coordinator;
connect with an SSO scheme listed in the auth-module-mappings flag.
```

The deny rule applies to arbitrary scheme names as well as to `basic`, so a
client cannot bypass the SSO privilege model by sending a made-up scheme.

<Callout type="info">
**Anybody can log in until a `COORDINATOR_WRITE` role exists.** Condition 3 is
what makes coordinator SSO self-bootstrapping. On a coordinator that starts with
`--auth-module-mappings` set but an empty role set, SSO cannot yet grant a
privileged session to anybody — so basic auth stays open, and you use it to
create the first role and grant it `COORDINATOR_WRITE`. The moment that grant
commits to Raft, basic auth closes on the next login attempt and SSO takes over.
**No coordinator restart is required.**
privileged session to anybody — so the passthrough stays open, and you use a
basic-auth connection to create the first role and grant it `COORDINATOR_WRITE`.
The moment that grant commits to Raft, the passthrough closes on the next login
attempt and SSO takes over. **No coordinator restart is required.**

The same rule applies in reverse: if you drop or revoke the last
`COORDINATOR_WRITE` role on a live cluster, basic auth reopens rather than
leaving the cluster unadministrable.
`COORDINATOR_WRITE` role on a live cluster, the passthrough reopens rather than
leaving the cluster unadministrable. Unlisted schemes are admitted during
break-glass in the same way as `basic`/`none`.
</Callout>

<Callout type="warning">
**Break-glass on license loss.** If the enterprise license is missing, expired
or invalid, SSO rejects every login. Condition 2 above means basic auth falls
back to the passthrough in exactly that case, so a license transition can never
lock every Bolt session out of a coordinator. Use that session to re-install the
license over Bolt:
or invalid, SSO rejects every login. Condition 2 above means `basic`/`none` and
unlisted schemes fall back to the passthrough in exactly that case, so a license
transition can never lock every Bolt session out of a coordinator. Use that
session to re-install the license over Bolt:

```cypher
SET DATABASE SETTING 'enterprise.license' TO 'License';
Expand All @@ -174,7 +206,7 @@ refresh.

### A follower without quorum cannot be logged into

Both the basic-auth decision and the SSO role check need the **leader's**
Both the passthrough decision and the SSO role check need the **leader's**
committed role set, and both are **fail-closed**: when the leader cannot be
reached, the login is rejected rather than validated against possibly-stale
local replicated state, which could still list a dropped role or an
Expand All @@ -191,14 +223,14 @@ license:
can't be validated. Retry once a leader is elected.
```

- **Basic/none logins are also rejected.** An unknown role set is not treated as
"no writable role", so the break-glass path does not open during a transient
leader outage.
- **Passthrough logins (`basic`/`none` and unlisted schemes) are also
rejected.** An unknown role set is not treated as "no writable role", so the
break-glass path does not open during a transient leader outage.

This is intentional and temporary: SSO is unavailable in that window anyway, and
access returns as soon as a leader is elected. If SSO is **not** configured, the
basic-auth passthrough never contacts the leader, so it keeps working on a
partitioned follower.
passthrough never contacts the leader, so it keeps working on a partitioned
follower.

### SSO authentication

Expand Down Expand Up @@ -298,11 +330,10 @@ a session whose roles were revoked mid-flight can still inspect who it is.

- `SHOW CURRENT USER` returns the principal the identity provider authenticated.
It is purely session-local and works even when the leader is unreachable. A
basic-auth passthrough session authenticated no principal and returns `null`.
passthrough session authenticated no principal and returns `null`.
- `SHOW CURRENT ROLE` returns the session's roles **filtered against the
leader's committed role set**, so it stops naming a role that `DROP ROLE`
already removed. A basic-auth passthrough session has no roles and returns
`null`.
already removed. A passthrough session has no roles and returns `null`.

### Auth queries rejected on coordinators

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -910,11 +910,11 @@ SHOW CURRENT ROLE;
- **No privilege and no license are required** — these are self-service queries
that reveal only the session's own identity.
- `SHOW CURRENT USER` returns the principal the SSO module reported. It is
session-local and works even when the leader is unreachable. A basic-auth
passthrough session returns `null`.
session-local and works even when the leader is unreachable. A passthrough
session (basic auth or any scheme not mapped to an SSO module) returns `null`.
- `SHOW CURRENT ROLE` returns the session's roles filtered against the leader's
committed role set, so a dropped role stops being reported. A basic-auth
passthrough session has no roles and returns `null`.
committed role set, so a dropped role stops being reported. A passthrough
session has no roles and returns `null`.

## Error handling

Expand Down
5 changes: 5 additions & 0 deletions pages/data-streams.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,11 @@ the following Memgraph flag:
The `INTERVAL_TIME` is measured in `milliseconds` and the default value is
`500ms`.

The queries a transformation returns for one batch run in one transaction. If
they include [auth
queries](/database-management/authentication-and-authorization#run-auth-queries-in-a-transaction),
they must all be auth queries.

## Setting a stream offset

When using a Kafka stream, you can manually set the offset of the next consumed
Expand Down
108 changes: 108 additions & 0 deletions pages/database-management/authentication-and-authorization.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,114 @@ and
[Replication](/clustering/replication)
documentation.

## Run auth queries in a transaction

You can run auth queries, such as `CREATE USER`, `CREATE ROLE`, `GRANT`, and
`SET ROLE`, in an [explicit
transaction](/fundamentals/transactions#explicit-transactions). Other sessions
and REPLICAs see none of the changes until `COMMIT`, and then all of them, so a
user never exists without the privileges you meant to give it. Available since
Memgraph 3.14.

```cypher
BEGIN;
CREATE USER alice IDENTIFIED BY 'alice_password';
CREATE ROLE analyst;
GRANT MATCH TO analyst;
SET ROLE FOR alice TO analyst;
COMMIT;
```

This example uses roles, which need [Memgraph
Enterprise](/database-management/enabling-memgraph-enterprise). The
transaction itself works in Memgraph Community too.

Auth transactions are serializable. Each query sees the changes made by the
queries before it. Memgraph snapshots each user or role the first time the
transaction reads the user or role, and later reads return that snapshot. If
anything the transaction has read changes before `COMMIT`, the commit fails.
`ROLLBACK` discards all of the transaction's changes. After this transaction,
neither `bob` nor `dave` exists:

```cypher
BEGIN;
CREATE USER bob;
CREATE USER dave;
ROLLBACK;
```

A single auth query outside a transaction works as before.

### What an auth transaction can contain

The first query inside a transaction decides the kind of transaction, either
data or auth. After an auth query, the transaction accepts only auth queries,
including the `SHOW` queries that read users, roles, and privileges. After any
other query type, it refuses auth queries: auth and data queries can't be mixed
within a single transaction.

```cypher invalid
BEGIN;
CREATE USER carol;
MATCH (n) RETURN count(n);
```

Either way, the refused query fails with this error:

```plaintext copy=false
A transaction that runs an auth query can contain only auth queries. Run other queries in a separate transaction.
```

The other queries refused in an auth transaction include `SHOW TRANSACTIONS`,
replication queries, and [user profile](/database-management/authentication-and-authorization/user-profiles)
queries.

User and [tenant profile](/database-management/tenant-profiles) changes are
refused in every explicit transaction. Run them as single queries.

### Conflicts between transactions

Memgraph doesn't lock users or roles while a transaction is open. At `COMMIT`,
it checks whether another session has changed anything the transaction read or
wrote. If it has, nothing is applied and the commit fails with this error:

```plaintext copy=false
Cannot resolve conflicting transactions. Retry this transaction when the conflicting transaction is finished.
```

The error is transient, so a driver's retry logic runs the transaction again
(see [conflicting transactions](/help-center/errors/transactions#conflicting-transactions)).
Two transactions that change different users or roles both commit.

Some queries read more than their names suggest, so they conflict more often:

- **Listing queries,** such as `SHOW USERS`: the transaction depends on the
whole list, so the commit fails if another session created or dropped a user
in the meantime.
- **`DROP ROLE`:** checks every user's roles, so it conflicts with any role
assignment in another session, even of a different role.
- **The first user:** on an instance with no users, two transactions that each
create a user conflict. With an Enterprise license, creating the first user
also creates the built-in roles, so it conflicts with a concurrent
`CREATE ROLE`.

The commit also fails with this error if another session holds the system
lock for more than 100 ms, for example while it runs a replication or
multi-tenancy query.

A transaction that grants, denies, or revokes a database, or sets a user's main
database, fails at `COMMIT` if another session dropped that database in the
meantime:

```plaintext copy=false
Tried to retrieve an unknown database "sales".
```

### Auth transactions and replication

A REPLICA applies a committed auth transaction whole, so it never holds some of
the transaction's changes without the rest.

## [Users](/database-management/authentication-and-authorization/users)

Learn how to manage users in Memgraph.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ Memgraph's privilege system controls access to various database operations throu
| `SHOW TRANSACTIONS` | `TRANSACTION_MANAGEMENT` | `SHOW TRANSACTIONS` |
| `TERMINATE TRANSACTIONS` | `TRANSACTION_MANAGEMENT` | `TERMINATE TRANSACTIONS 'transaction_id'` |
| `TERMINATE TRANSACTIONS "*"` | `TRANSACTION_MANAGEMENT` | `TERMINATE TRANSACTIONS "*"` terminates every transaction the user may terminate. Without the privilege, only the user's own transactions are terminated. |
| `SHOW SESSIONS` | **None** | `SHOW SESSIONS` lists the user's own sessions. With the `TRANSACTION_MANAGEMENT` privilege, it also lists other users' sessions on the databases where the user has the privilege. |
| `TERMINATE SESSIONS` | **None** | `TERMINATE SESSIONS 'session_id'` terminates the user's own other sessions. Terminating another user's session needs the `TRANSACTION_MANAGEMENT` privilege on the database that session is using. |
| `RELOAD BOLT_SERVER TLS` | `RELOAD_TLS` | `RELOAD BOLT_SERVER TLS` |
| `RELOAD INTRA_CLUSTER TLS` | `RELOAD_TLS` | `RELOAD INTRA_CLUSTER TLS` |

Expand Down
Loading
Loading