Infrastructure

View as Markdown

mz-deploy apply converges your infrastructure objects declaratively — it creates what’s missing and alters what has drifted. This page covers all object types managed by apply.

Overview

mz-deploy apply applies all types in dependency order: clusters → roles → network policies → secrets → connections → sources → tables. Each step is idempotent — running apply multiple times converges to the same state.

Preview changes before applying:

mz-deploy apply --dry-run

Skip secrets (useful in CI where secret values aren’t available):

mz-deploy apply --skip-secrets

You can also target individual object types with subcommands for granular control:

mz-deploy apply clusters
mz-deploy apply secrets

Clusters

-- clusters/orders.sql
CREATE CLUSTER orders (SIZE = '25cc');

apply creates missing clusters and alters drifted configuration. Grants and comments are applied idempotently.

Roles

-- roles/order_reader.sql
CREATE ROLE order_reader;

Secrets

Secret values use client-side provider functions that are resolved at apply time. This means compile works without access to actual secret values.

Use env_var() to read values from environment variables:

-- models/materialize/public/pg_user.sql
CREATE SECRET pg_user AS env_var('PG_USER');
-- models/materialize/public/pg_password.sql
CREATE SECRET pg_password AS env_var('PG_PASSWORD');

Alternatively, use aws_secret() to pull values from AWS Secrets Manager:

-- models/materialize/public/pg_password.sql
CREATE SECRET pg_password AS aws_secret('prod/pg-password');

aws_secret() requires an aws_profile in your project.toml:

[profiles.default.security]
aws_profile = "my-aws-profile"

apply secrets is idempotent — it runs CREATE SECRET IF NOT EXISTS then ALTER SECRET to update the value.

Connections

Postgres connection using secrets:

-- models/materialize/public/pg_conn.sql
CREATE CONNECTION pg_conn TO POSTGRES (
    HOST 'my-postgres.example.com',
    DATABASE 'app',
    USER SECRET pg_user,
    PASSWORD SECRET pg_password,
    SSL MODE 'require'
);

Sources

Postgres source:

-- models/materialize/public/pg_source.sql
CREATE SOURCE pg_source
IN CLUSTER orders
FROM POSTGRES CONNECTION pg_conn
(PUBLICATION 'mz_source');

Tables

-- models/materialize/public/orders.sql
CREATE TABLE orders FROM SOURCE pg_source
(REFERENCE public.orders);

After apply tables, the table’s column schema is automatically captured in types.lock. This is how compile knows what columns orders has when type-checking views that reference it. See Local development — Lock types for details.

Back to top ↑