diff --git a/docs/web/feature-engineering/materialized-views.mdx b/docs/web/feature-engineering/materialized-views.mdx
index eda98891e..15dcf64ce 100644
--- a/docs/web/feature-engineering/materialized-views.mdx
+++ b/docs/web/feature-engineering/materialized-views.mdx
@@ -73,23 +73,22 @@ argument; every refresh is a full one.
Enterprise
-`create_materialized_view` works on a `db://` connection as well as a local one.
-What changes is where the refresh runs -- across the cluster rather than in your
-process -- and that SQL can drive it:
+`create_materialized_view` and `refresh` also work on a `db://` connection.
+There the SDK sends them to the deployment as SQL -- `CREATE MATERIALIZED VIEW`
+and `REFRESH MATERIALIZED VIEW` -- and the work runs on the cluster rather than
+in your process. `source_version` is for local views only; the SDK refuses it
+on a remote refresh.
-```sql
-REFRESH MATERIALIZED VIEW chunks
-```
+Materialized views are experimental on a deployment, which has to have them
+enabled. How its refresh works -- rebuilding the whole view, as above, or
+reconciling what changed in the source -- depends on its LanceDB Enterprise
+version and configuration, and so do the options
+[`REFRESH MATERIALIZED VIEW`](/sql/dml/refresh#refresh-materialized-view)
+accepts.
-`WITH (full = true)` recomputes every row instead of reconciling what changed
-in the source since the last refresh. `SHOW MATERIALIZED VIEWS` lists them, which is
-cheaper than `list_materialized_views` -- that method finds views by reading
-every table's schema, so it costs one open per table.
-
-
-`CASCADE` is accepted by the parser but not yet implemented. A view built on
-another view is refreshed by refreshing each in dependency order.
-
+`SHOW MATERIALIZED VIEWS` lists them, which is cheaper than
+`list_materialized_views` -- that method finds views by reading every table's
+schema, so it costs one open per table.
## Working with the view {#working-with-the-view}
diff --git a/docs/web/management/index.mdx b/docs/web/management/index.mdx
index ce8ac9105..1d4d4eeba 100644
--- a/docs/web/management/index.mdx
+++ b/docs/web/management/index.mdx
@@ -52,7 +52,7 @@ See [Tables](/management/table) for creating one and shaping its schema.
| | Python | TypeScript | SQL |
| --- | --- | --- | --- |
-| create | `create_materialized_view` | `createMaterializedView` | -- |
+| create | `create_materialized_view` | `createMaterializedView` | `CREATE MATERIALIZED VIEW` |
| open | `open_materialized_view` | `openMaterializedView` | -- |
| list | `list_materialized_views` | `listMaterializedViews` | `SHOW MATERIALIZED VIEWS` |
| refresh | `refresh` | `refresh` | `REFRESH MATERIALIZED VIEW` |
diff --git a/docs/web/management/materialized-view.mdx b/docs/web/management/materialized-view.mdx
index 9a03a4270..a3f52d63c 100644
--- a/docs/web/management/materialized-view.mdx
+++ b/docs/web/management/materialized-view.mdx
@@ -49,7 +49,7 @@ separate definition step.
| | Python | TypeScript | SQL |
| --- | --- | --- | --- |
-| create | `create_materialized_view` | `createMaterializedView` | -- |
+| create | `create_materialized_view` | `createMaterializedView` | `CREATE MATERIALIZED VIEW` |
| open | `open_materialized_view` | `openMaterializedView` | -- |
| list | `list_materialized_views` | `listMaterializedViews` | `SHOW MATERIALIZED VIEWS` |
| refresh | `refresh` | `refresh` | `REFRESH MATERIALIZED VIEW` |
@@ -76,8 +76,11 @@ rows. Both are properties; on an async view, the definition is read with
## Against a deployment {#deployment}
Enterprise `create_materialized_view` works on a
-`db://` connection as well as a local one. What changes is that a refresh runs
-across the cluster rather than in your process, and SQL can drive it.
+`db://` connection as well as a local one. There the SDK creates and refreshes
+the view through SQL, and the work runs on the cluster rather than in your
+process. Materialized views are experimental on a deployment and have to be
+enabled there; see
+[Against a deployment](/feature-engineering/materialized-views#availability).
## What to read next {#next}
diff --git a/docs/web/sql/ddl/materialized-view.mdx b/docs/web/sql/ddl/materialized-view.mdx
index e5920f0d5..eeb053639 100644
--- a/docs/web/sql/ddl/materialized-view.mdx
+++ b/docs/web/sql/ddl/materialized-view.mdx
@@ -1,9 +1,9 @@
---
title: "Materialized View"
sidebarTitle: "Materialized View"
-description: "SHOW MATERIALIZED VIEWS — creation and refresh are SDK and REFRESH statements, not CREATE."
+description: "CREATE MATERIALIZED VIEW and SHOW MATERIALIZED VIEWS; refreshing is a REFRESH statement."
icon: table
-keywords: ["materialized view", "show materialized views", "sql"]
+keywords: ["materialized view", "create materialized view", "show materialized views", "sql"]
---
Enterprise [SQL runs on a deployment.](/sql)
@@ -12,13 +12,22 @@ A materialized view stores a query's result as rows, kept current by a refresh
-- the counterpart to a [view](/sql/ddl/view), which stores only the query.
-There is no `CREATE MATERIALIZED VIEW` statement. Creation is
-[`create_materialized_view`](/management/materialized-view#create) in the SDK,
-since it needs SDK-level source-table validation (stable row ids) that a bare
-SQL statement has nowhere to check. Once created, it is entirely a SQL object:
-queried like a table, refreshed with SQL, listed with SQL.
+Materialized views are experimental on a deployment, which has to have them
+enabled. Which statements and query shapes a deployment accepts, and how its
+refresh works, depend on its LanceDB Enterprise version and configuration.
+## CREATE MATERIALIZED VIEW {#create}
+
+```sql
+CREATE MATERIALIZED VIEW AS SELECT ...
+```
+
+On a `db://` connection, the SDK's
+[`create_materialized_view`](/management/materialized-view#create) sends this
+statement. Once created, a view is queried like a table, refreshed with SQL and
+listed with SQL.
+
## SHOW MATERIALIZED VIEWS {#show}
```sql
@@ -37,7 +46,7 @@ REFRESH MATERIALIZED VIEW chunks
```
See [REFRESH](/sql/dml/refresh#refresh-materialized-view) for the full syntax,
-including `full = true` and what `CASCADE` does not yet do.
+including `CASCADE` and `full = true`.
## Dropping one {#drop}
@@ -46,17 +55,18 @@ A materialized view **is** a table, so it is dropped with
stored rows, unlike dropping a [view](/sql/ddl/view#drop).
-**Enterprise job type:** `mat_view_refresh` for the refresh; `drop_table` for
-dropping it, same as any table.
+**Enterprise job type:** `mat_view_refresh` for a refresh, or `sql` on a
+deployment that rebuilds views through SQL; `drop_table` for dropping one, same
+as any table.
## What to read next {#next}
- Creating one from the SDK, and the stable-row-ids requirement.
+ Creating one from the SDK.
- Incremental refreshes, and what they cost.
+ What a refresh recomputes, locally and on a deployment.
diff --git a/docs/web/sql/dml/refresh.mdx b/docs/web/sql/dml/refresh.mdx
index 3fece1f70..2d00c1104 100644
--- a/docs/web/sql/dml/refresh.mdx
+++ b/docs/web/sql/dml/refresh.mdx
@@ -61,7 +61,7 @@ memory and GPU options there.
## REFRESH MATERIALIZED VIEW {#refresh-materialized-view}
```sql
-REFRESH MATERIALIZED VIEW [WITH (