Skip to main content

Authoring Templates

You can author your own stack templates to reproduce a multi-resource setup on demand. A template starts private to your organization, and you can later share it with colleagues or publish it to the platform marketplace.

Template structure

A template has two parts: a metadata envelope and a descriptor that declares the resources the stack composes.

curl -X POST https://api.foundrydb.com/stacks/templates \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-cms",
"display_name": "My CMS",
"description": "A PostgreSQL-backed Directus installation.",
"version": "1.0.0",
"visibility": "private",
"descriptor": {
"apiVersion": "stacks.foundrydb.com/v1",
"resources": [
{
"name": "db",
"kind": "database",
"spec": {
"database_type": "postgresql",
"version": "17",
"plan_name": "tier-2",
"storage_size_gb": 50,
"storage_tier": "maxiops"
}
},
{
"name": "app",
"kind": "app",
"spec": {
"attachment_kind": "directus",
"attached_to": "$db"
}
}
],
"dependencies": {
"app": ["db"]
}
}
}'

The template starts in draft publication status and is only visible to your organization.

Descriptor fields

FieldRequiredDescription
apiVersionYesMust be stacks.foundrydb.com/v1.
resourcesYesList of resource definitions. At least one required.
dependenciesNoMaps a resource symbolic name to the list of resource names that must reach Running before it is created. Defines provisioning order.
costPreview.inferenceBudgetUsdMonthlyNoMonthly spend ceiling for any inference key the stack mints. Shown as an is_ceiling line item in cost previews.

Resource kinds

Each resource in resources has a name (symbolic, used in $ref tokens and dependencies), a kind, and a spec.

database

Provisions a managed database service.

Spec keyRequiredDescription
database_typeYespostgresql, mysql, mongodb, valkey, kafka, or opensearch.
versionYesEngine version string (e.g. "17" for PostgreSQL).
plan_nameYesCompute plan (e.g. "tier-2").
storage_size_gbNoData disk size in GB. 1–1024.
storage_tierNo"standard" or "maxiops".
extensionsNoList of database extensions to enable (e.g. ["pgvector", "postgis"]).

files

Provisions an object-storage bucket.

Spec keyRequiredDescription
quota_soft_gbNoSoft quota in GB. 1–1024.
quota_hard_gbNoHard quota in GB. 1–1024.

inference

Mints an EU-routed inference key against your organization's configured provider.

Spec keyRequiredDescription
eu_onlyNoBoolean. When true, requests are restricted to EU inference endpoints.
monthly_budget_usdNoPer-month spend ceiling in USD. Shown as is_ceiling: true in cost previews.

app

Deploys a hosted application. The platform wires database credentials and bucket credentials into the app's environment automatically via attached_to references.

Trusted (private and org-shared) templates:

Spec keyRequiredDescription
attachment_kindNoFirst-party companion app identifier (e.g. "open-webui", "directus", "metabase", "nocodb", "hasura"). Mutually exclusive with image_ref.
image_refNoContainer image reference for a custom app. Not allowed in public templates.
container_portNoPort the container listens on. Not allowed in public templates.
plan_nameNoCompute plan.
storage_size_gbNoDisk size in GB. 1–1024.
storage_tierNo"standard" or "maxiops".
attached_toNo$ref pointing to a database or files resource whose credentials should be injected.
envNoCustom environment variables. Subject to env-shadow protection (see below).
authNoBasic auth config for the app's endpoint.
domainNoCustom domain for the app.

Public templates have a narrower allow-list. The image_ref, container_port, and env keys are not available. A public template's app must use a first-party companion app via attachment_kind.

Cross-resource references

Use $ref tokens in spec values to wire one resource's output into another's configuration. The reconciler resolves them after the upstream resource reaches Running.

{
"name": "app",
"kind": "app",
"spec": {
"attachment_kind": "open-webui",
"attached_to": "$db"
}
}

The platform injects the appropriate connection variables (see Env-shadow protection) based on the upstream resource kind.

Env-shadow protection

When your app resource includes an env map, the following keys are reserved by the platform and may not be set by a template author:

  • DATABASE_URL — injected when attached_to points to a database.
  • S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY, S3_SECRET — injected when attached_to points to a files resource.
  • Any key starting with MDB_ — reserved for platform-injected connection metadata.

Attempting to set any of these keys in env will fail validation with a descriptive error. The restriction applies at template save, at publish, and again at every launch as a defense in depth.

OPENAI_* keys are not restricted and are intentionally available for wiring the minted inference key into your application.

Storage sizing bounds

Any storage_size_gb, quota_soft_gb, or quota_hard_gb value must be between 1 and 1024 GB. Values outside this range are rejected at save time.

Dependency ordering

dependencies is a map from resource symbolic name to a list of resource names that must reach Running before it is created. Resources with no entries in dependencies are created in parallel in topological order.

{
"dependencies": {
"app": ["db", "files"],
"inference": []
}
}

In this example, db, files, and inference are created in parallel. app is created only after both db and files are Running.

Editing a template

A template in draft, rejected, or unpublished status can be updated:

curl -X PATCH https://api.foundrydb.com/stacks/templates/$TEMPLATE_ID \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"description": "Updated description.",
"version": "1.1.0",
"descriptor": { ... }
}'

On PATCH, only supplied fields are updated. A published or in-review template is immutable: create a new template (with a new name and version) to replace it.

Deleting a template

curl -X DELETE https://api.foundrydb.com/stacks/templates/$TEMPLATE_ID \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN"

Returns 204 No Content. Stacks already launched from this template keep running on their own snapshotted descriptor. Deletion prevents new launches from this template only.

Validation rules by visibility

Ruleprivateorg_sharedpublic
image_ref allowed on appYesYesNo
container_port allowed on appYesYesNo
env allowed on appYesYesNo
App must use attachment_kindNoNoYes
Storage size max 1024 GBYesYesYes
MDB_*, DATABASE_URL, S3_* env keys blockedYesYesYes

Validation runs at save, at publish, and at every launch. A template that pre-dates a tightened rule and has not been re-saved will fail at launch if it no longer passes the current rules.

Next steps

Once your template is ready, see Publishing and the Marketplace to share it with your organization or the wider platform.