Declare structures
A virtual data structure is how you tell Orkestia what your app stores. You do not create Postgres tables by hand. You declare databases, tables, fields, indexes, uniqueness, and an ownership policy. The platform validates a safe profile and applies it through data.appdata.structure.apply.
With dry_run=true, apply returns the compiled plan (and serving SQL when the compiler emits it) without writing. With dry_run=false, it writes catalog metadata (appdata_database, appdata_table, appdata_field, appdata_policy) and, when the plan includes serving DDL, executes that DDL on the app's serving backend — the instance the catalog points at, not a DSN you supplied.
Shape
databases:
- slug: farm
tables:
- slug: property
ownership:
kind: organization # owner | app | organization
capability_namespace: property
fields:
- { slug: name, type: text, required: true }
- { slug: hectares, type: number }
- { slug: active, type: bool }
Ownership is the isolation contract. Set it when you declare the table — changing it later is a migration, not a query-time flag. See Ownership & workspaces.
A table that is a log rather than a set — messages, run events, an outbox — also declares an append policy, which gives it server-allocated positions and exactly-once replay. See Ordered append.
ownership.kind | Who the rows belong to |
|---|---|
owner (default) | The signed-in end-user. Every op is filtered to that principal. |
app | Shared catalog / seed data for the app. Org seed goes through appdata.publish-as-app. |
organization | A workspace inside your app (a farm, a clinic, a tenant). Scoped to the user's active workspace and gated by workspace role. |
Apply
An org-member token (dashboard, SDK, or MCP agent) starts the apply workflow with the compiled plan. Exact input fields live in the catalog under data.appdata.structure.apply.
discover data.appdata.structure.apply
get schema
start — plan + identity_app_uuid
watch
What you get back
After a successful apply, the structure is metadata Orkestia owns:
- Virtual database / table / field definitions scoped to
(organization, identity app). - Per-table access policy (owner-forced, owner-only, capability namespace).
- An audit trail of applied plans.
No DSN is returned. Callers use record workflows or the Data API. Operators inspect the live database in Query.
Rules of thumb
- Prefer narrow fields and uniqueness you actually need. Uniqueness is enforced by the platform, not by your app.
- Do not invent a second tenant column "to be safe" — ownership + the injected principal is the tenant filter.
- Keep shared reference data on
ownership.kind: appand tenant business data onownerororganization. - Resolve live workflow names from the catalog. Do not copy slugs from this page into production without checking.
App Data
Platform-owned application data — declare tables, never hold a DSN in the frontend. Workflows, Data API, PostgREST, and an admitted SQL console for operators.
Records & Data API
Create, read, query, update, and delete App Data rows through typed workflows or the App Data MCP — structured filters, never SQL from the browser
