Skip to content
instancezinstancez

Configuration

Complete instancez.yaml schema reference. Every key, type, default, and example.

instancez.yaml is the single source of truth for your project. On boot, the server diffs it against the live database and applies migrations automatically.

Env vars are interpolated using ${VAR} or ${VAR:-default}. They are resolved at load time; references are never stored in the database.

A JSON Schema for this file is published at https://docs.instancez.ai/schema/instancez.json. Add this as the first line of instancez.yaml for completion and inline errors in editors that use the YAML language server (VS Code YAML extension, Neovim, JetBrains):

# yaml-language-server: $schema=https://docs.instancez.ai/schema/instancez.json

inz init writes the line for you. Numbers and booleans also accept a ${VAR} string.

Key Type Required Description
version integer yes Schema version. Currently 1.
Key Type Default Description
project.name string — Display name shown in the dashboard.
project.description string — Optional project description.
project.cloud.project_id string — Cloud project ID. Written automatically by inz cloud deploy --new; not meant to be hand-edited.
Key Type Default Description
database.pool.max integer 20 Maximum connections in the request pool.
database.pool.min integer 5 Minimum idle connections.
database.pool.idle_timeout duration 300s How long idle connections are held before closing.
Key Type Default Description
server.port integer 8080 HTTP listen port.
server.max_body_size string 1MB Maximum request body size for non-upload endpoints. Cannot raise Instancez Cloud’s ~6MB request cap.
server.max_limit integer 1000 Most rows one REST table read, setof RPC, or top-level has-many embed returns (PostgREST db-max-rows). Applies with or without limit/Range; Content-Range shows the capped range. -1 disables the cap.

Methods (GET, POST, PUT, PATCH, DELETE, OPTIONS), headers, credentials, and preflight caching are fixed platform defaults — origins is the only knob, matching Supabase’s own gateway. Changes to origins and server.max_body_size apply on config reload (inz dev file watch, dashboard save) without a restart.

Key Type Default Description
server.cors.origins string[] [] Allowed origins. Use ["*"] to allow all.
Key Type Default Description
server.timeouts.request duration 25s Read/write deadline for /rest/v1 and /auth/v1 requests. Storage, functions, admin and dashboard routes are exempt.
server.timeouts.db_query duration 10s statement_timeout for every API query (all roles), applied per transaction. Prefer: statement-timeout=<ms> can lower it for one request. 0 or empty disables it.
server.timeouts.upload duration 5m Deadline for file upload requests.
server.timeouts.shutdown duration 30s Graceful shutdown window.

Duration strings use Go format: 30s, 5m, 1h.

Key Type Default Description
providers.email.type string — Email provider type. Currently "resend" or "ses".
providers.email.api_key string — Provider API key. Supports ${VAR}.
providers.email.default_from_email string — Default sender address.

Set providers.email: null to disable email sending.

Key Type Default Description
providers.storage.type string — "local", "s3" or "gcs".
providers.storage.path string — (local only) Directory for local file storage.
providers.storage.bucket string — (s3 and gcs) Bucket name. Required.
providers.storage.region string — (s3 only) AWS region.
providers.storage.access_key_id string — (s3 only) AWS access key. Supports ${VAR}.
providers.storage.secret_access_key string — (s3 only) AWS secret key. Supports ${VAR}.
providers.storage.endpoint string — (s3 only) Custom endpoint URL for S3-compatible stores.

Auth is always provisioned, even if auth: is omitted entirely; the block only overrides defaults.

Key Type Default Description
auth.jwt_expiry duration 15m Access token lifetime.
auth.refresh_token_expiry duration 7d Refresh token lifetime. Refresh tokens are always issued.
auth.allow_signup boolean true Allow public sign-up: POST /auth/v1/signup, first-time signInWithOtp, and first-time OAuth / ID-token sign-in. Set to false for invite-only; blocked sign-ups get 422 signup_disabled, except first-time signInWithOtp, which returns an empty 200.
auth.allow_anonymous boolean false Allow anonymous sign-in (empty-body signup). Off by default; set true to enable.
auth.redirect_urls string[] [] Allowlist of origins for post-auth redirects (OAuth, email verification). The server’s own origin is always allowed.

auth.refresh_tokens is deprecated and ignored — refresh tokens are always issued.

Key Type Default Description
auth.email.verify_email boolean false Require email verification before the user can sign in. Requires a configured email provider.
auth.email.templates map — Override built-in email templates by name (e.g. confirm, recovery).
auth.email.templates.<name>.subject string — Email subject line.
auth.email.templates.<name>.body string — Inline HTML/text body.
auth.email.templates.<name>.body_file string — Path to a file containing the body (alternative to body).

OAuth provider configuration. Providers are keyed by name under auth.oauth; the name (google, github, apple, …) selects the built-in provider implementation.

Key Type Default Description
auth.oauth.<name>.client_id string — OAuth client ID. Supports ${VAR}.
auth.oauth.<name>.client_secret string — OAuth client secret. Supports ${VAR}. Optional for google and apple (only signInWithIdToken works without it; the redirect flow needs it), required for other providers.
auth.oauth.<name>.redirect_url string — OAuth callback URL registered with the provider.

apple takes a Services ID plus optional iOS bundle IDs and an ES256 JWT client_secret; see Auth.

Tables map to Postgres tables in the public schema by default. The migrator diffs this block against the live database on each boot.

tables:
posts:
schema: public # optional; default "public"
rls_enabled: true # recommended; see RLS page
fields:
- name: id
type: bigserial
primary_key: true
- ...
indexes:
- ...
rls:
- ...
Key Type Default Description
fields[].name string required Column name.
fields[].type string required Postgres type (e.g. text, bigint, uuid, timestamptz, text[]).
fields[].primary_key boolean false Mark as primary key. Mark several fields for a composite key. The key’s columns can’t change once the table exists, except for dropping a single key column and adding one new key column in the same change.
fields[].required boolean false Add NOT NULL constraint.
fields[].unique boolean false Add UNIQUE constraint.
fields[].default any — Column default. Supported: literal values, now(), current_date, current_time. The shorthand uuid_v7() and uuid_v4() are normalized to gen_random_uuid().
fields[].enum string[] — Restrict values to this list (creates a CHECK constraint).
fields[].pattern string — Regex pattern for a CHECK constraint.
fields[].min number — Minimum numeric value (inclusive).
fields[].max number — Maximum numeric value (inclusive).
fields[].check string — Raw SQL CHECK expression.
fields[].foreign_key.references string — table.column or schema.table.column. table.column is public; use auth.users.id for auth users.
fields[].foreign_key.on_delete string restrict cascade, restrict, or set_null. Defaults to restrict when omitted.
fields[].auto_updated_at boolean false Set the column to now() on every UPDATE. Only on timestamp/timestamptz fields.
fields[].immutable boolean false Reject any UPDATE that changes the column (error 23514, HTTP 400), for every role including the secret key. INSERT is unaffected; an upsert that hits a conflict counts as an update.

No columns are injected automatically. Every column, including primary keys, must be declared.

A composite primary key marks each of its fields:

tables:
memberships:
fields:
- name: team_id
primary_key: true
foreign_key:
references: teams.id
- name: user_id
type: uuid
primary_key: true

To reference one column of a composite key from another table’s foreign_key, that column must be unique on its own: add a unique index on it (indexes: [{columns: [serial], unique: true}]). unique: true on an existing column adds no constraint. See Schema.

Key Type Default Description
rls_enabled boolean inferred: true if rls has policies, else false Turn row-level security on or off for the table. true with no policies denies anon/authenticated everything. false with policies is a validation error. Leaving it unset produces a validation warning. See RLS.
Key Type Default Description
timestamps boolean false Appends created_at (timestamptz, required, default now()) and updated_at (same, plus auto_updated_at: true) after the declared fields. Declaring either column as well is a validation error. Removing timestamps later drops both columns, so it needs --allow-destructive. A dashboard save writes the expanded fields, not the shorthand.
Key Type Default Description
indexes[].columns string[] required Columns to index.
indexes[].unique boolean false Create a unique index.
indexes[].where string — Partial index condition (SQL expression).
indexes[].method string btree btree, hash, gin, gist, brin or spgist. unique needs btree. Changing it rebuilds the index.

RLS is the only authorization layer. Declare policies here; instancez creates them automatically. Whether RLS itself is on is controlled by rls_enabled, not by whether this list is empty.

Key Type Default Description
rls[].operations string[] required One or more of select, insert, update, delete.
rls[].using string conditional SQL boolean expression selecting which existing rows the operation can see or target.
rls[].with_check string conditional SQL boolean expression deciding what a written row is allowed to look like.
rls[].type string permissive permissive or restrictive.
rls[].owner string — Shorthand for <column> = auth.uid() in using and with_check (whichever the operations read). operations defaults to all four. The column must be uuid. Cannot be combined with using/with_check. A dashboard save writes the expanded form.

Useful SQL helpers available in RLS expressions:

  • auth.uid() — UUID of the authenticated user (null for anonymous).
  • auth.is_authenticated() — true when the request carries a valid user JWT.

Bucket definitions. Buckets cannot be created, modified, or deleted at runtime; only instancez.yaml changes take effect. Bucket names follow the identifier rules, and public, sign, authenticated, info, upload, list, move, copy and v1 are reserved because they’re storage route segments.

storage:
avatars:
public: false
max_size: 5MB
types:
- image/png
- image/jpeg
rls:
- operations: [select]
using: "true"
Key Type Default Description
storage.<name>.public boolean false Allow anyone to download via /storage/v1/object/public/..., which skips RLS. Grants no select; listing and writes still follow rls.
storage.<name>.max_size string 50MB Maximum file size per upload (e.g. 5MB, 1GB). Does not lift the ~4.5MB cap on server-proxied uploads on Instancez Cloud; use POST /storage/<bucket>/sign for larger files.
storage.<name>.types string[] [] Allowed MIME types. Wildcards like image/* are accepted. Empty means all types allowed.
storage.<name>.rls RLSPolicy[] [] Same policy shape as table RLS, applied to storage.objects.

Postgres stored procedures exposed at /rest/v1/rpc/<name>.

rpc:
search_posts:
description: Full-text search
auth_required: false
language: plpgsql # sql | plpgsql (default: plpgsql)
volatility: stable # volatile | stable | immutable (default: volatile)
security: invoker # invoker | definer (default: invoker)
args:
- name: query
type: text
required: true
returns:
type: "setof posts"
body: |
SELECT * FROM posts WHERE body @@ plainto_tsquery(query);
Key Type Default Description
rpc.<name>.description string — Documentation string.
rpc.<name>.auth_required boolean false Reject unauthenticated callers.
rpc.<name>.language string plpgsql sql or plpgsql.
rpc.<name>.volatility string volatile volatile, stable, or immutable. Only stable/immutable can be called with GET.
rpc.<name>.security string invoker invoker or definer.
rpc.<name>.args[].name string required Argument name.
rpc.<name>.args[].type string required Postgres type.
rpc.<name>.args[].required boolean false Return 404 PGRST202 (with a hint naming the argument) if absent.
rpc.<name>.args[].default any — Postgres DEFAULT for optional args. null or NULL emits DEFAULT NULL.
rpc.<name>.returns.type string — Return type: void, record, a scalar or composite type, setof <type>, or table(col type, …).
rpc.<name>.set map — Map of search_path, statement_timeout, lock_timeout, work_mem, emitted as SET on the function.
rpc.<name>.body string required Function body (PL/pgSQL or SQL).

JavaScript code functions served at /functions/v1/<name>. Distinct from rpc: (which declares Postgres stored procedures).

functions:
send_notification:
runtime: node
file: functions/send_notification.js
auth_required: true
timeout: 15s
env:
WEBHOOK_URL: https://hooks.example.com/notify
API_KEY: ${INSTANCEZ_ENV_NOTIFY_API_KEY}
Key Type Default Description
functions.<name>.runtime string required "node".
functions.<name>.file string required Path to the JS handler file, relative to the config root.
functions.<name>.auth_required boolean false Require a valid JWT. Returns 401 otherwise.
functions.<name>.timeout duration 30s Per-request timeout. Exceeded requests return 504.
functions.<name>.env map {} Env values injected as ctx.env. Values may be string literals or ${INSTANCEZ_ENV_*} references.

INSTANCEZ_ENV_* references are resolved from the process environment. Plain ${VAR} references (without the INSTANCEZ_ENV_ prefix) are not supported in env: — use them elsewhere in the config file for other values.

Split a large config across files. Only the main instancez.yaml may use it.

version: 1
include:
- tables/*.yaml
- rpc.yaml
  • Paths are relative to the main file’s directory. Glob characters (*, ?, [...]) are allowed only in the last path element, there is no **, and each pattern must match at least one file. ${VAR} and absolute paths are rejected.
  • An included file may only contain tables, storage, rpc and functions (empty files are fine). Nested include is an error.
  • The same table, bucket, rpc or function name in two files is an error. functions.<name>.file stays relative to the project root.
  • Every match must resolve inside the project directory, symlinks included. The main file is skipped if a glob matches it.
  • Errors in a fragment name the file and line. Line numbers in later validation errors refer to the merged document.
  • inz dev reloads when the main file or any included file changes, including a new file that matches a glob.
  • The dashboard cannot save a config that uses include: (GET /_admin/config/status reports read_only: true and the save returns 409 config_read_only); edit the YAML files instead.
  • inz validate, inz vet, inz gen, inz dev and inz serve read the merged config. S3 and bundle config sources do not support include; inz bundle, inz cloud deploy and inz validate --cloud send one merged file without the include: key; configs without include: are sent as written. Shorthands (timestamps, owner) are not expanded by the CLI, so cloud support for them needs a platform release.
  • A glob that matches only the main file logs a warning. Dotfiles and editor temp files (.x.swp, x~, #x#) are skipped by globs.

Bundle pointer for self-hosted deployments. inz bundle produces the value (e.g. s3://bucket/key#sha256 or gcs://bucket/key#sha256) and writes it here; the managed cloud stamps it server-side from uploaded sources. inz cloud deploy does not write this field.


version: 1
project:
name: My App
description: Example instancez project
server:
port: 8080
max_body_size: 5MB
max_limit: 500
cors:
origins: ["https://app.example.com"]
timeouts:
request: 30s
db_query: 10s
upload: 5m
shutdown: 30s
database:
pool:
max: 20
min: 5
idle_timeout: 300s
providers:
email:
type: resend
api_key: ${RESEND_API_KEY}
default_from_email: noreply@example.com
storage:
type: s3
bucket: my-app-storage
region: us-east-1
access_key_id: ${AWS_ACCESS_KEY_ID}
secret_access_key: ${AWS_SECRET_ACCESS_KEY}
auth:
jwt_expiry: 1h
refresh_token_expiry: 30d
allow_signup: true
allow_anonymous: false
redirect_urls:
- https://app.example.com
email:
verify_email: true
tables:
profiles:
rls_enabled: true
fields:
- name: id
foreign_key:
references: auth.users.id
on_delete: cascade
primary_key: true
- name: display_name
type: text
- name: avatar_url
type: text
rls:
- operations: [select]
using: "true"
- operations: [insert]
with_check: "auth.uid() = id"
- operations: [update]
using: "auth.uid() = id"
with_check: "auth.uid() = id"
storage:
avatars:
public: true
max_size: 2MB
types: [image/png, image/jpeg, image/webp]
rls:
- operations: [select]
using: "auth.uid() IS NOT NULL"
- operations: [insert]
with_check: "name LIKE auth.uid()::text || '/%'"
- operations: [delete]
using: "name LIKE auth.uid()::text || '/%'"
rpc:
profile_search:
language: sql
volatility: stable
args:
- name: q
type: text
required: true
returns:
type: "setof profiles"
body: |
SELECT * FROM profiles WHERE display_name ILIKE '%' || q || '%';
functions:
resize_avatar:
runtime: node
file: functions/resize_avatar.js
auth_required: true
timeout: 20s
env:
MAX_WIDTH: "512"