Skip to main content
A template with two or more services creates a stack: one resource that groups the apps, databases and Blob folders, keeps them connected and is updated, snapshotted and deleted as a unit. You do not declare the stack; it exists because services has more than one entry (up to 8). A template with a single app creates just that app, with no stack.

Declare the services

Each service is an entry of services. Apps, databases and Blob folders sit side by side, and the placeholders connect them:
Everything is created in one job. The order is: validation, the stack, the databases (the job waits for them to be ready), Blob folders, images, apps, variables, certificates, start, healthcheck and outputs. If any step fails, the platform deletes only what that job created, with no safety snapshot because nothing yet holds user data, and reports the step and the error.

Optional services

Make a database optional with when, or switch any service with sets.services in a question option. A service that is off is not created and its placeholders are empty. This is how one template offers “Postgres or SQLite” or “add workers”; see Options and sets. The memory of a service that is off does not count towards the required plan.

Several databases of the same engine

You can declare more than one database of the same engine, such as a Redis for cache and another for a queue. Each is a regular database with its own memory taken from the plan, and each has its own service id and placeholders. A database belongs to one stack only, and several apps of the stack can use the same database.

Blob folders

A blob service gives the stack the folder stacks/<stack-slug>/ and a key managed by the platform, restricted to that folder. The app reads it through the S3_*-style placeholders. If the user undoes the stack, the key is revoked and the files are kept. See the Blob service for the fields.

How the services connect

You never write an address. Use {{services.<id>.host}} or {{services.<id>.url}}. The app reaches the database through its public address, with client certificates. A network_mode other than public is refused with STACK_NETWORK_MODE_UNAVAILABLE.

Certificates

Databases require a client certificate. The platform writes the files into the app at /app/.vertra/certs/<database_id>/ at every start, read-only, and {{services.<id>.ssl.*_path}} gives you their absolute paths: The folder is reserved by the platform: it is skipped by code uploads, snapshot restores, rollbacks, downloads and “Save as template”, so a private key never travels with the code. If the user resets the database certificates, the platform rewrites the files and asks them to restart the app. Some drivers cannot take certificates by path alone. When yours reads them from the connection URL, use {{services.<id>.url}}; for Prisma 6, use {{services.<id>.prisma_url}}. See Connect an app to a database for how each driver reads the certificates.

Connecting app to app

One app reaches another through its public URL, so the called app needs web: required or web: optional and is exposed on the internet. The platform does not authenticate the call: if you want only your own app to be accepted, check a shared secret on both sides:
Your api must refuse a request without that token.

Variables managed by the stack

Variables that come from a placeholder of a database, Blob folder or app are managed: they carry a “managed by the stack” badge and update on their own when a password, certificate or address changes. The platform tells the user the app must restart. Editing one by hand turns it into a regular variable.

Updates

A stack that came from your template updates all its services together: a safety snapshot of every member, then the services one after another, and a full return to the snapshot if one fails. Resources the user added to the stack by hand are ignored by updates. See Updates and rollback.

Placeholders and inputs

Every database and Blob placeholder.

Stacks for users

What the user sees and can do with a stack.
Last modified on October 30, 2026