Choose materialization deliberately
Good candidates include:- a dashboard aggregate read many times between source changes;
- a reporting join whose source query is expensive;
- a stable export or automation input that can tolerate bounded staleness;
- a governed source-action workset that benefits from a refreshed snapshot.
Create and configure
- Open Databases → Materialized Views and choose Add.
- Build a Structured definition or, when explicitly enabled for Resource Admin, a read-only raw SQL definition.
- Preview the output and verify unique aliases, casts, grouping, and result types.
- In Materialization, select at least one output column as the concurrent refresh key.
- Add optional output indexes for frequent filters and sorting.
- Configure the View ACL and save.
- Query the saved data, then create a Schedule when recurring freshness is required.
lastRefreshAt records explicit later refreshes; a newly created materialization can therefore contain initial rows before that field has a value.
Concurrent refresh key
uniqueKey is required and must reference output columns. RevoEngine ensures there is a unique index covering that key because the managed concurrent-refresh contract requires one. Choose columns that are truly unique in the complete result; a refresh fails when the query produces duplicate key values.
Optional indexes are structured btree indexes over materialized output:
- at most 64 index definitions;
- 1–32 distinct output columns per index;
- optional identifier-safe name up to 63 characters;
- optional uniqueness.
Read and filter materialized output
Materialized and regular Views use the same Query Database View data operation and the same output query model: projection, filters, sorting, grouping, casts,take, skip, and optional count.
Readers see the last completed materialization while a concurrent refresh builds the replacement. A failed refresh does not publish partial new rows. Use lastRefreshAt as the successful freshness timestamp and lastRefreshRunId as the identifier of that refresh operation.
The list UI exposes Last refreshed only for Materialized Views. For a stronger application SLA, store the source watermark in the View output and compare it with business time; lastRefreshAt shows execution time, not how recent every source record is.
Manual refresh
Use Refresh in the workspace or call Refresh a materialized Database View. The endpoint responds with HTTP 202, but the current contract is not a queued background request: the HTTP request completes after the concurrent refresh succeeds andlastRefreshAt plus lastRefreshRunId are stored. A successful response therefore means the new materialization is available.
There is no separate manual-refresh polling resource. If the connection ends without a success response, read the View again and compare its refresh metadata before retrying.
Scheduled refresh
For recurring refresh:- Save the Materialized View.
- Open Schedule from the Materialization builder or navigate to Automation → Schedules.
- Choose target type Materialized view and select the saved View.
- Set the five-field cron expression and an IANA timezone.
- Save and activate the Schedule.
lastRefreshRunId. Monitor the Schedule for deployment state and Jobs for individual execution outcomes.
An active Schedule is a lifecycle dependency: delete the Schedule before deleting the Materialized View or converting it to a regular View.
See Schedules for cron, timezone, activation, and operational history. API clients should use the generated Schedule contract because the UI’s Materialized view choice is normalized to the current Platform-operation target fields.
Governed source actions and asynchronous preview
Structured Materialized Views can drive the same explicit source update/delete workflow as regular Views, but their preview has an additional freshness boundary:- Preview the action.
- The API returns HTTP 202 with
operationIdandPENDING. - Poll Get a Database View action preview.
- The operation moves through
PENDINGorRUNNINGtoCOMPLETEDorFAILED. - On completion, review the affected count and sample keys, then use the returned mutation token.
lastRefreshRunId changes.
This is the asynchronous refresh-related flow in the Database Views API. Do not confuse its status with manual refresh, which has no polling operation.
Lifecycle semantics
Limits and failure behavior
- Materialized Views share the instance Database resource quota with Tables and regular Views.
- Structured and raw previews return at most 1000 rows; raw preview also has a 15-second statement timeout.
- A refresh fails if the View is not materialized, the unique constraint cannot be satisfied, a source/query is invalid, or the database cannot complete concurrent refresh.
- Refresh metadata changes only after success. Keep the prior successful timestamp as the recovery signal.
- A scheduled failure is recorded as an error Job and does not mark the View freshly completed.
- Update failures roll back the relation rebuild rather than saving only part of the new definition.
- Materialization does not use the application Database Cache namespace. Size contributes to database usage, while Cache TTL/persist/delete operations apply only to cache keys.
- Reading a materialization does not emit source Table row-audit entries. A governed action does, when audit is enabled on the mutated source Table.
Production checklist
- Define a measurable freshness objective.
- Use a genuinely unique, stable refresh key.
- Index only observed filter and sort paths.
- Keep pages bounded and project only required output fields.
- Schedule expensive refreshes outside workload peaks.
- Monitor Job errors and
lastRefreshAt, not only Schedule activation. - Remove dependent Schedules before conversion or deletion.
- Re-preview after any source schema or cast change.
- Require a fresh action preview before source mutation.
Related API operations
- Create a Database View
- Get a Database View
- Update a Database View
- Query Database View data
- Refresh a materialized Database View
- Export readable relation data

