Project structure
View as MarkdownAn mz-deploy project is a directory of SQL files and configuration. Directories
map to Materialize objects, and configuration files control connection and
deployment behavior.
Directory layout
A typical project looks like this:
order-monitoring/
├── models/
│ └── materialize/
│ ├── public.sql # Schema modifier
│ └── public/
│ ├── order_summary.sql # View definition
│ └── stalled_orders.sql # Materialized view definition
├── clusters/
│ └── orders.sql # Cluster definition
├── roles/
│ └── order_reader.sql # Role definition
├── network-policies/ # Network policy definitions
├── project.toml # Project configuration
├── types.lock # Column schemas (generated)
├── README.md
└── .gitignore
The models/ directory contains all schema-scoped objects: views, materialized
views, sinks, tables, sources, connections, and secrets. These live under
models/<database>/<schema>/ because they belong to a specific database and
schema.
The clusters/, roles/, and network-policies/ directories have their own
top-level directories because these are global objects — they are not scoped
to any database or schema.
File-path-to-object-name mapping
The path of each SQL file under models/ determines the fully qualified object
name in Materialize:
models/<database>/<schema>/<object>.sql → database.schema.object
For example, models/materialize/public/stalled_orders.sql creates the object
materialize.public.stalled_orders.
Model files
Each model file contains one primary CREATE statement that defines the object.
Supported primary statements are:
CREATE VIEWCREATE MATERIALIZED VIEWCREATE SINKCREATE TABLE/CREATE TABLE FROM SOURCECREATE SOURCECREATE CONNECTIONCREATE SECRET
You can include companion statements in the same file for related configuration:
CREATE INDEX, COMMENT ON, GRANT.
Here is a complete example:
-- models/materialize/public/stalled_orders.sql
CREATE MATERIALIZED VIEW stalled_orders
IN CLUSTER orders AS
SELECT
id,
customer,
amount,
created_at,
updated_at,
mz_now() - updated_at AS stalled_for
FROM orders
WHERE status = 'pending'
AND updated_at < mz_now() - INTERVAL '30 minutes';
CREATE INDEX stalled_orders_customer_idx IN CLUSTER orders
ON stalled_orders (customer);
COMMENT ON MATERIALIZED VIEW stalled_orders IS
'Orders stuck in pending status for more than 30 minutes.';
GRANT SELECT ON stalled_orders TO order_reader;
Schema modifiers
A file at models/<database>/<schema>.sql is a schema modifier. Use it for
schema-level statements that apply to the schema as a whole rather than to a
specific object. A schema modifier can contain:
SET api = stableCOMMENT ON SCHEMAGRANTALTER DEFAULT PRIVILEGES
For example:
-- models/materialize/public.sql
COMMENT ON SCHEMA public IS 'Order monitoring data model.';
GRANT USAGE ON SCHEMA public TO order_reader;
Database modifiers
A file at models/<database>.sql is a database modifier. Use it for
database-level statements:
COMMENT ON DATABASEGRANTALTER DEFAULT PRIVILEGES
project.toml
The project.toml file in your project root controls project-wide settings:
mz_version— the Materialize version used to runtestandexplainlocally (it selects the Docker image). Set to"cloud"to use the latest cloud version.dependencies— external dependency declarations for objects your project references but does not own. See Local development for details.- Per-profile config sections — override settings for specific environments. See Profiles for multi-environment setup.
The active connection profile is resolved per-invocation from --profile,
MZ_DEPLOY_PROFILE, or the per-checkout default set by mz-deploy profile set. See Profiles.
profiles.toml
The profiles.toml file (typically at ~/.mz/profiles.toml) stores your
Materialize connection details. Each section defines a named profile:
[default]
host = "<your-materialize-host>"
port = 6875
username = "<your-username>"
password = "<your-password>"
See Profiles for multi-environment setup and advanced configuration.