Skip to main content
fjall services reads the live ECS rollout state of every service in an application and exits non-zero unless all of them have finished rolling out. The exit code is the point of the command. A CloudFormation deploy can report success while a background worker is still churning behind it. An ALB health endpoint only covers the web service. This command asserts that every service converged.
  • Signed in. Run fjall login. Credentials live at ~/.fjall/auth.json (or $FJALL_CONFIG_DIR/auth.json).
  • A connected AWS account. Run fjall connect if you have not connected one yet.
  • A matching organisation binding. Run the command inside your Fjall project. The command refuses to read services when the project is bound to a different organisation than the one you are signed in to.
  • A deployed application. The probe reads the application’s Compute stack, so the application must have been deployed at least once. When the stack is absent, or it emits no DeployableService export, the command fails with a message naming the stack and telling you to deploy the application first. A stack the CLI cannot read is reported as a read failure with its cause, never as an application without services.
  • Node.js 22.3 or later.

Check rollout status

The <app> positional argument is required.
Wire it into a pipeline directly after a deploy:

What happens

  1. The CLI reads the application’s Compute stack outputs and takes every output whose export name carries the DeployableService marker. Each one’s value must be an ECS service ARN, and its export name must be the name the contract builds from that ARN’s own cluster and service. An export whose name and value disagree fails the command, naming the output — it is never read as whichever of the two it appears to say. Each service is addressed on its own cluster, so an application whose services span clusters is probed cluster by cluster.
  2. --service <name> filters that list. Matching is case-insensitive against the live ECS service name, by exact match or suffix, so --service worker matches api-worker.
  3. ECS describes each service, and Fjall reads the PRIMARY deployment on each one.
  4. The results print as one row per service, then a verdict line.
  5. The process exits 0 only when every service completed.
The command is read-only. It describes ECS services and changes nothing.
From fjall 39 nothing is matched by application-name containment. The stack read is the one Fjall names for the application, and every output claiming the contract is verified against its own ARN — so the collision class fjall 38’s token-boundary match narrowed (two applications in one account and region whose names differ only by their separators) cannot arise here at all. See the 19 September 2026 entry in the changelog.

Completion rule

A service counts as complete when ECS reports rolloutState: COMPLETED. Services on a deployment controller that does not report a rollout state fall back to steady-state arithmetic: exactly one active deployment, running count equal to desired count, and zero pending tasks. A service with no PRIMARY deployment is never complete.

Human output

Each row is prefixed with ✓ when that service completed and ✗ when it has not. An incomplete service prints the ECS rollout state reason on an indented line below its row. The run ends with either ✓ All N service(s) completed their rollout or ✗ Not all services have completed their rollout.

JSON output

--json writes a single JSON document to stdout and silences the surrounding step output. Diagnostics and error text stay on stderr, so stdout is safe to pipe into jq.
Every entry carries the clusterName and clusterArn it runs on; there is no document-level cluster, because an application’s services need not share one. rolloutState, rolloutStateReason, failedTasks, and taskDefinition appear only when ECS supplies them. rolloutStateReason is AWS-authored prose and is masked before it reaches stdout. A service the Compute stack exports but ECS could not describe carries ecsFailureReason instead — MISSING when the cluster no longer holds it. Such a service reports zero counts, is never completed, and so holds allCompleted at false. The command reports it rather than dropping it: a service that has vanished from its cluster is the case you most need to see. The JSON document is written before the non-zero exit on an incomplete rollout, so a CI step can parse the result and still fail the build.

Agent mode

fjall services has no agent output surface. Passing --agent, --budget, --fields, or --full on the command line is refused with an error naming the alternative:
Use --json instead.

Exit codes

Exit 1 covers both a genuine incomplete rollout and a failed probe. Failures that land on 1 include: not signed in, no connected AWS account, an organisation-binding mismatch, no ECS services found for the application, no service matching --service, and a failed ECS describe call. Distinguish the two cases from the output rather than the code. With --json, a completed probe always emits the document and sets allCompleted. A failed probe emits nothing on stdout and writes the reason to stderr. Without --json, an incomplete rollout writes Rollout incomplete for api: api-worker in cluster api to stderr, naming each service that has not converged and the cluster it runs on. Two clusters in one application may hold a service of the same name, so the name alone does not identify it.

Options

Next Steps

fjall deploy

Deploy an application to AWS, then run this check against it.

fjall rollout

Restart running services so rotated secrets take effect.

fjall releases

Review recorded releases and their image tags.

fjall ci

Run deploys and smoke checks from a CI pipeline.