apply creates applications before the databases they depend on — a first apply always deploys against nothing #45

Closed
opened 2026-07-14 17:55:30 +00:00 by dan-claude-bot · 1 comment
dan-claude-bot commented 2026-07-14 17:55:30 +00:00 (Migrated from github.com)

What happens

On a first apply, cast creates resources in manifest order — applications, then databases, then services. So a compose application is created (and Coolify deploys it) before the Postgres and Redis it talks to exist.

Observed on a fresh box: core was created, Coolify built it, started five containers, and the one-shot migrate service exited 1 — because the database it migrates was not going to exist for another few seconds' worth of API calls. A full build, a full deploy, and a red deployment in the UI, guaranteed, on every first apply.

Why it is worth fixing even though the first deploy fails anyway

On this project the first deploy is expected to fail regardless — DATABASE_URL is a pending-coolify-generated placeholder until the two-pass bootstrap fills it in, and no ordering saves that. So this is not a correctness bug today.

It becomes one the moment a manifest has no generated secrets — a project pointing at an external managed database, say — where the only reason the first apply fails is that cast built the app before its dependencies. And it is a cost today regardless: a wasted build, and a red deploy that an operator has to be told to ignore. A tool whose first run always looks broken teaches people to ignore its output, which is the last habit you want in something that mutates production.

Suggested

Create in dependency order:

databases → services → applications

This is exactly the reverse of the teardown order proposed for cast destroy (#43) — applications → services → databases — and the symmetry is the point: things come up in the order their dependencies allow, and go down in the reverse.

Within a kind, order is not significant.

Worth noting the ordering cannot be derived from the manifest — nothing declares that core needs postgres — so it has to be the fixed kind-order above rather than a computed graph. That is fine: Coolify's resource kinds are few and the dependency direction between them is not in question.

## What happens On a first apply, cast creates resources in manifest order — **applications, then databases, then services**. So a compose application is created (and Coolify deploys it) *before* the Postgres and Redis it talks to exist. Observed on a fresh box: `core` was created, Coolify built it, started five containers, and the one-shot `migrate` service exited 1 — because the database it migrates was not going to exist for another few seconds' worth of API calls. A full build, a full deploy, and a red deployment in the UI, guaranteed, on every first apply. ## Why it is worth fixing even though the first deploy fails anyway On this project the first deploy is *expected* to fail regardless — `DATABASE_URL` is a `pending-coolify-generated` placeholder until the two-pass bootstrap fills it in, and no ordering saves that. So this is not a correctness bug today. It becomes one the moment a manifest has **no** generated secrets — a project pointing at an external managed database, say — where the only reason the first apply fails is that cast built the app before its dependencies. And it is a cost today regardless: a wasted build, and a red deploy that an operator has to be *told* to ignore. A tool whose first run always looks broken teaches people to ignore its output, which is the last habit you want in something that mutates production. ## Suggested Create in dependency order: ``` databases → services → applications ``` This is exactly the reverse of the teardown order proposed for `cast destroy` (#43) — applications → services → databases — and the symmetry is the point: things come up in the order their dependencies allow, and go down in the reverse. Within a kind, order is not significant. Worth noting the ordering cannot be derived from the manifest — nothing declares that `core` needs `postgres` — so it has to be the fixed kind-order above rather than a computed graph. That is fine: Coolify's resource kinds are few and the dependency direction between them is not in question.
dan-claude-bot commented 2026-07-14 22:35:28 +00:00 (Migrated from github.com)

#60 depends on this. Deriving an app's DATABASE_URL from the database resource requires the database to exist before the app's env is resolved — so on a from-nothing apply, ${resource:postgres.url} has nothing to resolve against until this lands.

Second, harder reason to fix the ordering: today it means "a first apply deploys against nothing" (recoverable — the next deploy works). With #60 it would mean the env cannot be computed at all.

#60 depends on this. Deriving an app's `DATABASE_URL` from the database resource requires the database to exist before the app's env is resolved — so on a from-nothing apply, `${resource:postgres.url}` has nothing to resolve against until this lands. Second, harder reason to fix the ordering: today it means "a first apply deploys against nothing" (recoverable — the next deploy works). With #60 it would mean the env cannot be computed at all.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/cast#45
No description provided.