The requires field
Most real apps need a database. Traditionally, you'd provision one manually, copy the connection string into an env var, and hope nobody forgets a step. With a Launchfile, you declare what you need and it's provisioned for you when you deploy.
The requires field declares: "My app needs this resource — provision it and give me connection details." The database creation, user setup, and credential injection are handled for you at deploy time.
Build it up
requires: [postgres] — the shorthand syntax for declaring a database dependency.version: launch/v1
name: my-app
runtime: node
commands:
start: "node server.js"
requires: [postgres]requires: [postgres]
# is equivalent to:
requires:
- type: postgresset_env to wire the database connection into your app. $url resolves to the actual connection string at deploy time.version: launch/v1
name: my-app
runtime: node
commands:
start: "node server.js"
requires:
- type: postgres
set_env:
DATABASE_URL: $urlGET /health is expected to return a 2xx response.version: launch/v1
name: my-app
runtime: node
commands:
start: "node server.js"
requires:
- type: postgres
set_env:
DATABASE_URL: $url
health: /healthrequires: [postgres]requires:
- type: postgresProvisioning hints with config
A requires entry also takes a config map, which passes provisioning hints straight to whatever provisions the resource — for Postgres, the one you'll reach for most is extensions, the list of Postgres extensions the database should have installed.
config. How — or whether — a provider honors them is provider-specific.requires:
- type: postgres
config:
extensions: [vector]
set_env:
DATABASE_URL: $urlThe docker provider maps known package names to the SQL name CREATE EXTENSION expects (vector, not pgvector) and swaps in a Postgres image that ships it. The macos-dev provider does no such mapping — it drops your string straight into CREATE EXTENSION and, if that fails, continues silently, so an unrecognized name produces no error and no extension.
On docker, extensions are only created the first time a database's data directory initializes. Add config.extensions to an app that's already deployed, and the provider warns instead of applying it — naming the service and config.extensions, and pointing you to two remedies: run launchfile down --destroy then launchfile up to recreate the data (and the extensions) from scratch, or run the CREATE EXTENSION statements against the running database yourself to keep the data. See the spec's Resource configuration section for the full key list, and Lesson 8, Expressions & Resource Configuration, for naming, versioning, and config together.
How expressions work
Inside set_env, you can reference properties of the provisioned resource using $ expressions:
$url— Full connection URL (e.g.postgres://user:pass@host:5432/dbname)$host— Database hostname$port— Port number$user— Username$password— Password$name— Database name
These are expressions that resolve to real values at deploy time. Use $url when your framework expects a single connection string, or individual fields when it expects them separately.
Typos are easy to make and would otherwise resolve to an empty string — so launchfile validate warns when a property isn't in the standard vocabulary for the resource type (e.g. $hoost on postgres) and lists the properties that are. It's a warning, not an error: providers may expose extra properties beyond the standard set.
In the wild
Miniflux is a minimalist feed reader that needs Postgres. Notice how it uses set_env to wire the database, declares env vars with defaults, and even generates a secret for the admin password.
version: launch/v1
name: miniflux
description: "Minimalist and opinionated feed reader"
repository: https://github.com/miniflux/v2
logo: https://raw.githubusercontent.com/miniflux/v2/main/internal/ui/static/bin/icon-512.png
image: miniflux/miniflux:latest
provides:
- name: web
protocol: http
port: 8080
exposed: true
tls: server-cert
requires:
- type: postgres
set_env:
DATABASE_URL: $url
supports:
# Miniflux switches the SAME listen address to TLS when both files are
# supplied: internal/http/server/server.go:115 computes hasCertFiles and
# :135-141 selects the TLS server. CERT_FILE, KEY_FILE and PORT are
# configuration options (internal/config/options.go:121, :312, :519).
- name: server-cert
type: certificate
set_env:
PORT: "8080"
CERT_FILE: $cert_file
KEY_FILE: $key_file
env:
RUN_MIGRATIONS:
default: "1"
description: "Run database migrations on startup"
CREATE_ADMIN:
default: "1"
description: "Create admin user on first run"
ADMIN_USERNAME:
default: "admin"
description: "Admin username"
ADMIN_PASSWORD:
required: true
sensitive: true
description: "Admin password"
generator: secret
BASE_URL:
default: $app.url
description: "Public-facing URL; miniflux uses it for absolute links and feed URLs"
health: /healthcheck
restart: alwaysrequires:- Declares a Postgres dependency — provisioned automatically when the app deploys.
set_env:- Injects the connection URL into the DATABASE_URL environment variable.
generator: secret- Auto-generates a secure admin password at deploy time — no manual setup needed.
health: /healthcheck- This endpoint is checked to verify the app is alive.
Try it: npx launchfile up miniflux to launch this app locally.View in catalog
Check your understanding
requiresdeclares resource dependencies — they're provisioned automatically.- Use
set_envwith$url,$host,$port, etc. to wire connection details into your app. - Shorthand (
[postgres]) and expanded syntax (- type: postgres) are equivalent. configpasses provider-specific provisioning hints, like Postgresextensions— how it's honored differs by provider.- Add
healthso your app's readiness can be verified after deployment.