diff --git a/modules/ROOT/content-nav.adoc b/modules/ROOT/content-nav.adoc
index 2d08c7ecc..0e4e2ba8b 100644
--- a/modules/ROOT/content-nav.adoc
+++ b/modules/ROOT/content-nav.adoc
@@ -15,6 +15,7 @@
** xref:clauses/call.adoc[]
** xref:clauses/create.adoc[]
** xref:clauses/delete.adoc[]
+** xref:clauses/filter.adoc[]
** xref:clauses/finish.adoc[]
** xref:clauses/foreach.adoc[]
** xref:clauses/limit.adoc[]
diff --git a/modules/ROOT/images/filter_clause.svg b/modules/ROOT/images/filter_clause.svg
new file mode 100644
index 000000000..f15e25ef6
--- /dev/null
+++ b/modules/ROOT/images/filter_clause.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/modules/ROOT/pages/appendix/gql-conformance/analogous-cypher.adoc b/modules/ROOT/pages/appendix/gql-conformance/analogous-cypher.adoc
index 0a13525c5..9c28c5f97 100644
--- a/modules/ROOT/pages/appendix/gql-conformance/analogous-cypher.adoc
+++ b/modules/ROOT/pages/appendix/gql-conformance/analogous-cypher.adoc
@@ -31,11 +31,6 @@ These codes order the features in the table below.
| * GQL's `PERCENTILE_CONT()` function is equivalent to Cypher's xref:functions/aggregating.adoc#functions-percentilecont[`percentileCont()`] function.
* GQL's `PERCENTILE_DISC()` function is equivalent to Cypher's xref:functions/aggregating.adoc#functions-percentiledisc[`percentileDisc()`] function.
-| GQ08
-| `FILTER` statement
-| Selects a subset of the records of the current working table.
-Cypher uses xref:clauses/with.adoc[`WITH`] instead.
-
| GQ09
| `LET` statement
| Adds columns to the current working table.
diff --git a/modules/ROOT/pages/appendix/gql-conformance/index.adoc b/modules/ROOT/pages/appendix/gql-conformance/index.adoc
index 2a09dc445..3b2ab5ad8 100644
--- a/modules/ROOT/pages/appendix/gql-conformance/index.adoc
+++ b/modules/ROOT/pages/appendix/gql-conformance/index.adoc
@@ -1,7 +1,7 @@
:description: Overview of Cypher's conformance to GQL.
= GQL conformance
-*Last updated*: 21 February 2025 +
+*Last updated*: 27 February 2025 +
*Neo4j version*: 2025.03
GQL is the new link:https://www.iso.org/home.html[ISO] International Standard query language for graph databases.
diff --git a/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc b/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc
index 64d09b71c..3cf0f8806 100644
--- a/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc
+++ b/modules/ROOT/pages/appendix/gql-conformance/supported-optional.adoc
@@ -173,6 +173,11 @@ For example, GQL’s graph reference values `CURRENT_GRAPH` and `CURRENT_PROPERT
| xref:queries/composed-queries/combined-queries.adoc[`UNION`]
|
+| GQ08
+| `FILTER` statement
+| xref:clauses/filter.adoc[`FILTER`]
+|
+
| GQ13
| `ORDER BY` and page statement: `LIMIT`
| xref:clauses/limit.adoc[`LIMIT`], xref:clauses/order-by.adoc[`ORDER BY`]
diff --git a/modules/ROOT/pages/clauses/filter.adoc b/modules/ROOT/pages/clauses/filter.adoc
new file mode 100644
index 000000000..cbe006eba
--- /dev/null
+++ b/modules/ROOT/pages/clauses/filter.adoc
@@ -0,0 +1,289 @@
+= FILTER
+:description: Information about Cypher's `FILTER` clause.
+:table-caption!:
+:page-role: new-2025.03
+
+`FILTER` is used to add filters to queries, similar to Cypher's xref:clauses/where.adoc[`WHERE`].
+Unlike `WHERE`, `FILTER` is not a subclause, which means it can be used independently of the xref:clauses/match.adoc[`MATCH`], xref:clauses/optional-match.adoc[`OPTIONAL MATCH`], and xref:clauses/with.adoc[`WITH`] clauses, but not within them.
+
+[[example-graph]]
+== Example graph
+
+The following graph is used for the examples below:
+
+image::filter_clause.svg[width="700",role="middle"]
+
+To recreate the graph, run the following query in an empty Neo4j database:
+
+[source, cypher, role=test-setup]
+----
+CREATE (andy:Swedish:Person {name: 'Andy', age: 36}),
+ (timothy:Person {name: 'Timothy', age: 38}),
+ (peter:Person {name: 'Peter', age: 35}),
+ (lisa:Person {name: 'Lisa', age: 48}),
+ (john:Person {name: 'John', age: 40}),
+ (susan:Person {name: 'Susan', age: 32}),
+ (andy)-[:KNOWS {since: 2012}]->(timothy),
+ (andy)-[:KNOWS {since: 1999}]->(peter),
+ (peter)-[:KNOWS {since: 2005}]->(lisa),
+ (lisa)-[:KNOWS {since: 2010}]->(john),
+ (john)-[:KNOWS {since: 2021}]->(susan)
+----
+
+
+[[basic-filtering]]
+== Basic filtering
+
+.Filter on a node label
+[source, cypher]
+----
+MATCH (n)
+FILTER n:Swedish
+RETURN n.name AS name
+----
+
+.Result
+[role="queryresult",options="header,footer",cols="1*(n:Person)
+FILTER r.since > 2010
+RETURN p.name AS person,
+ r.since AS knowsSince,
+ n.name AS otherPerson
+----
+
+.Result
+[role="queryresult",options="header,footer",cols="3* 40
+RETURN n.name AS name, n.age AS age
+----
+
+.Result
+[role="queryresult",options="header,footer",cols="2*(b:Person WHERE b.age > minAge)
+RETURN b.name AS name`
+----
+.Result
+[role="queryresult",options="header,footer",cols="1*(b:Person FILTER b.age > minAge)
+RETURN b.name AS name
+----
+
+For more information about how to use `WHERE` in fixed-length and variable-length pattern matching, see xref:clauses/where.adoc#filter-patterns[`WHERE` -> Filter patterns].
+
+=====
+
+[[filter-with-where]]
+=== `FILTER` as a substitute for `WITH * WHERE`
+
+Unlike `WHERE`, which relies on `MATCH`, `OPTIONAL MATCH`, or `WITH` to define its scope, `FILTER` can filter queries independently of these clauses.
+This can make some queries more concise.
+
+For example, the following two queries are equivalent:
+
+.Filter using `WITH * WHERE`
+[source, cypher]
+----
+UNWIND [1, 2, 3, 4, 5, 6] AS x
+WITH x
+WHERE x > 2
+RETURN x
+----
+
+.Filter using `FILTER`
+[source, cypher]
+----
+UNWIND [1, 2, 3, 4, 5, 6] AS x
+FILTER x > 2
+RETURN x
+----
+
+As such, `FILTER` can be seen as a substitute for the `WITH * WHERE ` constructs in Cypher.
+
+.Using `FILTER` instead of `WITH * WHERE` in `LOAD CSV`
+=====
+
+The following two xref:clauses/load-csv.adoc[`LOAD CSV`] commands are equivalent:
+
+.companies.csv
+[source, csv, filename="companies.csv"]
+----
+Id,Name,Location,Email,BusinessType
+1,Neo4j,San Mateo,contact@neo4j.com,P
+2,AAA,,info@aaa.com,
+3,BBB,Chicago, info@ ,G
+,CCC,Michigan,info@ccc.com,G
+----
+
+.`LOAD CSV` using `WITH * WHERE`
+[source, cypher]
+----
+LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
+WITH row
+WHERE row.Id IS NOT NULL
+MERGE (c:Company {id: row.Id})
+----
+
+.`LOAD CSV` using `FILTER`
+[source, cypher]
+----
+LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
+FILTER row.Id IS NOT NULL
+MERGE (c:Company {id: row.Id})
+----
+
+=====
+
+However, while `FILTER` can act as a substitute for `WITH * WHERE ` constructs, it does not include the ability of `WITH` to manipulate the variables in scope for subsequent clauses.
+Nor can `FILTER` alias or create new variables.
+In other words, `FILTER` only has the function of `WITH * WHERE ` and not `WITH AS WHERE `.
diff --git a/modules/ROOT/pages/clauses/load-csv.adoc b/modules/ROOT/pages/clauses/load-csv.adoc
index 084e738ff..5036d7a45 100644
--- a/modules/ROOT/pages/clauses/load-csv.adoc
+++ b/modules/ROOT/pages/clauses/load-csv.adoc
@@ -551,6 +551,9 @@ Neo4j does not store `null` values.
In the file `companies.csv`, some rows do not specify values for some columns.
The examples show several options of how to handle `null` values.
+[NOTE]
+The queries in this example use xref:clauses/filter.adoc#filter-with-where[`FILTER`] (introduced in Neo4j 2025.03) as a replacement for `WITH * WHERE `.
+
.companies.csv
[source, csv, filename="companies.csv"]
----
@@ -565,8 +568,7 @@ Id,Name,Location,Email,BusinessType
[source, cypher]
----
LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
-WITH row
-WHERE row.Id IS NOT NULL
+FILTER row.Id IS NOT NULL
MERGE (c:Company {id: row.Id})
----
@@ -574,8 +576,7 @@ MERGE (c:Company {id: row.Id})
[source, cypher]
----
LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
-WITH row
-WHERE row.Id IS NOT NULL
+FILTER row.Id IS NOT NULL
MERGE (c:Company {id: row.Id, hqLocation: coalesce(row.Location, "Unknown")})
----
@@ -583,8 +584,7 @@ MERGE (c:Company {id: row.Id, hqLocation: coalesce(row.Location, "Unknown")})
[source, cypher]
----
LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
-WITH row
-WHERE row.Id IS NOT NULL
+FILTER row.Id IS NOT NULL
MERGE (c:Company {id: row.Id})
SET c.email = nullIf(trim(row.Email), "")
----
diff --git a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc
index d23d39a03..9d215ee78 100644
--- a/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc
+++ b/modules/ROOT/pages/deprecations-additions-removals-compatibility.adoc
@@ -209,6 +209,33 @@ a|
label:functionality[]
label:new[]
+[source, cypher, role="noheader"]
+----
+UNWIND [1, 2, 3, 4, 5, 6] AS x
+FILTER x > 2
+RETURN x
+----
+
+[source, cypher, role="noheader"]
+----
+UNWIND [1, 2, 3, 4, 5, 6] AS x
+FILTER x > 2
+RETURN x
+----
+
+[source, cypher, role="noheader"]
+----
+LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
+FILTER row.Id IS NOT NULL
+MERGE (c:Company {id: row.Id})
+----
+
+| New xref:clauses/filter.adoc[`FILTER`] clause used to filter queries, similar to xref:clauses/where.adoc[`WHERE`].
+
+a|
+label:functionality[]
+label:new[]
+
[source, cypher, role="noheader"]
----
WHEN false THEN RETURN 1 AS x
diff --git a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc
index c6f0e495d..3390e4667 100644
--- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc
+++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc
@@ -748,6 +748,9 @@ RETURN status.transactionId AS transaction, status.committed AS commitStatus, st
=====
While failed transactions may be more efficiently retried using a link:{neo4j-docs-base-uri}/create-applications[driver], below is an example how failed transactions can be retried within the same Cypher query:
+[NOTE]
+The query below uses xref:clauses/filter.adoc#filter-with-where[`FILTER`] (introduced in Neo4j 2025.03) as a replacement for `WITH * WHERE `.
+
.Query retrying failed transactions
[source, cypher]
----
@@ -757,8 +760,7 @@ CALL (row) {
MERGE (y:Year {year: row.year})
MERGE (m)-[r:RELEASED_IN]->(y)
} IN 2 CONCURRENT TRANSACTIONS OF 10 ROWS ON ERROR CONTINUE REPORT STATUS as status
-WITH *
-WHERE status.committed = false
+FILTER status.committed = false
CALL (row) {
MERGE (m:Movie {movieId: row.movieId})
MERGE (y:Year {year: row.year})
diff --git a/modules/ROOT/pages/syntax/keywords.adoc b/modules/ROOT/pages/syntax/keywords.adoc
index 4e7a24477..dc71b20a2 100644
--- a/modules/ROOT/pages/syntax/keywords.adoc
+++ b/modules/ROOT/pages/syntax/keywords.adoc
@@ -164,6 +164,7 @@ Note that with future functionality, Cypher may be extended with additional keyw
* `FALSE`
* `FIELDTERMINATOR`
* `FINISH`
+* `FILTER`
* `FLOAT`
* `FOR`
* `FOREACH`