> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fjall.io/llms.txt
> Use this file to discover all available pages before exploring further.

# fjall deploy

> Deploy Fjall organisation infrastructure or applications to AWS with live deployment progress.

<Info>
  **Interactive command.** Guides you through selecting and deploying targets with real-time feedback.
</Info>

## Overview

`fjall deploy` ships your infrastructure to AWS. It handles organisation-level deployments (AWS Organization, SSO, accounts) and application deployments (compute, storage, networking).

## Prerequisites

* Logged in with `fjall login`.
* An AWS account connected with `fjall connect`.
* In organisation mode, an active deployment target selected with `fjall target set <name>`.

## Usage

```bash theme={null}
fjall deploy [target] [service] [options]
```

## Deploy Targets

`target` accepts an application name, one of `organisation`, `platform`, or `account`, or `domain <name>`. All are standalone deployable targets.

| Target          | Deploys                                                                                                 |
| --------------- | ------------------------------------------------------------------------------------------------------- |
| `<app-name>`    | Application infrastructure (ECS, Lambda), databases (RDS, Aurora, DynamoDB), networking, load balancers |
| `organisation`  | AWS Organization root, organisational units, service control policies, cost allocation tags             |
| `platform`      | AWS SSO configuration, shared services, IPAM pools, transit gateways                                    |
| `account`       | A single member account stack                                                                           |
| `domain <name>` | A managed domain's hosted zone, records, and certificates ([see below](#deploying-a-domain))            |

### Cascade behaviour

`organisation` cascades: it deploys the organisation infrastructure, then the platform and every member account. Opt out with `--no-cascade` to deploy the organisation stack alone.

`platform` and `account` never cascade. Each deploys its own stack only.

```bash theme={null}
# Deploy an application
fjall deploy api

# Deploy the organisation structure (cascades to platform + accounts)
fjall deploy organisation

# Deploy the organisation stack only
fjall deploy organisation --no-cascade

# Deploy the platform stack alone
fjall deploy platform
```

## Deploying a domain

```bash theme={null}
fjall deploy domain example.com
```

`fjall deploy domain <name>` routes through the same operation as
[`fjall domain deploy <name>`](/cli/domain#deploy-a-domain) — the two
spellings have identical flags and exit semantics.

| Option                                  | Description                                                                                                                                                                                                                                    |
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--skip-caa-preflight`                  | Pre-answer the delegated deploy's CAA preflight (you have verified the CAA chain out of band)                                                                                                                                                  |
| `--remediate <name/TYPE=verb>`          | Named consent for a record-takeover ticket row when adopting a live zone (e.g. `--remediate 'www.example.com/A'=recreate`; a weighted/latency/failover variant row carries its SetIdentifier: `--remediate 'www.example.com/A@blue'=recreate`) |
| `--destruction-consent-digest <digest>` | Bind consents to the ticket digest they were minted against                                                                                                                                                                                    |
| `--plan`                                | Compute and print the resource-level change plan plus any record-takeover ticket, then stop before any mutation (exit `2` = changes pending approval)                                                                                          |
| `--approval-token <token>`              | Resume an approved plan from a prior `--plan` run; the plan digest is re-verified before deploying                                                                                                                                             |

Domain-specific semantics:

* **`--allow-replace` is rejected** on domain deploys — not silently dropped.
  Consent to takeover rows with `--remediate '<name>/<TYPE>'=recreate` — or
  `--remediate '<name>/<TYPE>@<setIdentifier>'=recreate` when the live record
  set carries a SetIdentifier (weighted, latency, and failover variants are
  classified and consented per variant).
* **Exit `4`** means the takeover consent was withheld: success-shaped,
  nothing released, nothing deployed. See
  [Destructive Changes](/deployment/destructive-changes).
* **`--plan` runs the same two-step as application deploys** — a domain plan
  additionally prints any record-takeover ticket, exits `2` when changes are
  pending approval (nothing mutated), and resumes via `--approval-token`.

## Interactive Mode

Run without arguments for guided deployment:

```bash theme={null}
fjall deploy
```

The picker asks what to deploy, then which application:

```bash theme={null}
? What would you like to deploy today?
  ❯ Application - Cloud applications
    Organisation - AWS foundation

? Select application to deploy:
  ❯ api
    web
    dashboard
```

Choosing **Organisation** shows a cascade confirmation (`Deploy Organisation, Platform and Accounts?`). Choosing **Platform** or **Account** deploys that single stack immediately with no cascade prompt.

## Options

| Option                    | Description                                                                                                      | Example                                             |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| `-v, --verbose`           | Show detailed deployment logs                                                                                    | `fjall deploy -v`                                   |
| `--infra-only`            | Deploy infrastructure only (skip code)                                                                           | `fjall deploy api --infra-only`                     |
| `--deploy-only`           | Deploy code only (skip infrastructure)                                                                           | `fjall deploy api --deploy-only`                    |
| `--skip-build`            | Skip the Docker image build (use with `--deploy-only` when the image is already pushed)                          | `fjall deploy api --skip-build`                     |
| `--skip-migrations`       | Skip database migrations during this deployment                                                                  | `fjall deploy api --skip-migrations`                |
| `--skip-readiness-check`  | Skip the pre-deploy target readiness probe (application deploys only; the step is recorded as skipped in output) | `fjall deploy api --skip-readiness-check`           |
| `-f, --force`             | Redeploy all stacks even when no infrastructure changes are detected                                             | `fjall deploy api --force`                          |
| `--image-tag <tag>`       | Roll forward or back to an existing image tag (skips build, implies `--deploy-only`)                             | `fjall deploy api --image-tag api-sha-a1b2c3d4e5f6` |
| `--target <target>`       | Override the active deployment target for this deployment                                                        | `fjall deploy api --target production-us-use1`      |
| `--region <region>`       | Deploy to a specific region within the target's account                                                          | `fjall deploy api --region eu-west-1`               |
| `--all-regions`           | Deploy to all regions for the target's account                                                                   | `fjall deploy api --all-regions`                    |
| `-e, --environment <env>` | Free-form CI/CD label passed to CDK synthesis                                                                    | `fjall deploy api --environment prod`               |
| `--no-cascade`            | Skip automatic platform and account deployment after an organisation deploy                                      | `fjall deploy organisation --no-cascade`            |
| `--skip-confirmation`     | Skip the deployment confirmation prompt                                                                          | `fjall deploy api --skip-confirmation`              |
| `--non-interactive`       | Force plain CLI output (no UI)                                                                                   | `fjall deploy api --non-interactive`                |

### Plan and approval options

| Option                     | Description                                                                                                                                          | Example                                     |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
| `--plan`                   | Compute and print the resource-level change plan, then stop before any mutation (exit `0` = no changes, `2` = changes pending approval, `1` = error) | `fjall deploy api --plan`                   |
| `--require-approval`       | Engage the approval gate: refuse to mutate unless the plan is approved via `--auto-approve` or a prior `--approval-token`                            | `fjall deploy api --require-approval`       |
| `--auto-approve`           | Approve the computed plan without prompting (use with `--require-approval`, or in CI to proceed past changes)                                        | `fjall deploy api --auto-approve`           |
| `--approval-token <token>` | Resume an approved plan from a prior `--plan` run; the plan digest is re-verified before applying                                                    | `fjall deploy api --approval-token <token>` |

### Destructive-change consent options

These satisfy the [destruction gate](/deployment/destructive-changes) when a deploy would destroy or replace a stateful resource:

| Option                                  | Description                                                                                                                                       | Example                                                                              |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| `--remediate <name=verb>`               | Named consent for a pending destructive change (repeatable; exact, case-sensitive physical name)                                                  | `fjall deploy api --remediate api-db=recreate`                                       |
| `--allow-replace <name>`                | Shorthand consent: allow the named resource to be replaced (repeatable; equivalent to `--remediate <name>=recreate`)                              | `fjall deploy api --allow-replace api-db`                                            |
| `--destruction-consent-digest <digest>` | Bind consents to the ticket digest from a prior `--plan` run; the deploy withholds if the pending destructive changes have changed since the plan | `fjall deploy api --remediate api-db=recreate --destruction-consent-digest <digest>` |

<Note>
  `-e, --environment <env>` does not select an account or region. It is an optional free-form label for CI/CD that flows into CDK synthesis as a context value. The account is chosen by the active target (or `--target`), not by `--environment`.
</Note>

## Choosing the Deploy Account

In organisation mode, the account a deploy lands in is the **active deployment target**, an account plus region pair named `<accountname>-<regionabbrev>` (for example `production-us-use1`).

| Step                                        | Command                               |
| ------------------------------------------- | ------------------------------------- |
| List derived targets (active marked with ▸) | `fjall target list`                   |
| Show the active target                      | `fjall target get`                    |
| Set the active target                       | `fjall target set production-us-use1` |

At deploy time the account resolves in this order:

1. The per-deploy `--target <name>` flag, when present.
2. Otherwise the `activeTarget` stored in `fjall-config.json`. With exactly one target it is selected automatically; with several you must run `fjall target set` first.

Targets are derived at runtime from your organisation config (fetched from the Fjall API), not authored by hand. See [Understanding Profiles](/deployment/understanding-profiles) for how authentication and account selection fit together.

## Deployment Process

### 1. Pre-flight Checks

Fjall validates:

* AWS credentials and permissions
* Target exists and is valid
* Required dependencies installed
* No conflicts with existing resources
* The stacks are not wedged by resources deleted outside CloudFormation (a confirmed out-of-band deletion blocks the deploy and points you at [`fjall drift`](/cli/drift))

### 2. Infrastructure Synthesis

For each deployment, Fjall:

* Compiles the TypeScript CDK code
* Generates CloudFormation templates
* Calculates resource changes
* Identifies security implications

### 3. Deployment Preview

```bash theme={null}
Deploying api...
Build complete
Synthesis complete

Resources to create:
  + AWS::ECS::Cluster (ApiCluster)
  + AWS::ECS::Service (ApiService)
  + AWS::RDS::DBCluster (ApiDatabase)
  + AWS::ElasticLoadBalancingV2::LoadBalancer
  + AWS::EC2::SecurityGroup (3)

Security Changes:
  New IAM policies will be created

Deploy? (y/N)
```

<Note>
  If the computed plan would **destroy or replace a stateful resource**, the
  deploy stops at an unconditional gate before anything is applied and asks
  for consent by exact resource name. No flag skips it. See [Destructive
  Changes](/deployment/destructive-changes).
</Note>

### 4. Deployment Execution

Fjall creates the CloudFormation stacks, monitors progress, handles dependencies, and reports errors immediately.

### 5. Post-Deployment

After a successful deployment, Fjall displays resource endpoints, connection strings, next steps, and updates local configuration.

## Examples

### Deploy the organisation first time

```bash theme={null}
# Deploy organisation structure (cascades to platform + accounts)
fjall deploy organisation

# Or deploy each stack independently
fjall deploy platform
fjall deploy account
```

### Deploy an application

```bash theme={null}
# Interactive selection
fjall deploy

# Direct deployment
fjall deploy api

# Non-interactive (CI/CD)
fjall deploy api --non-interactive
```

### Infrastructure vs code

```bash theme={null}
# Infrastructure changes only
fjall deploy api --infra-only

# Application code only (faster)
fjall deploy api --deploy-only

# Roll back to a known-good image tag
fjall deploy api --image-tag api-sha-a1b2c3d4e5f6
```

<Note>
  Fjall image tags are content-addressed: `<service>-sha-<12 hex chars of the
      image digest>`. Find the tags for an application in its ECR repository (AWS
  console or `aws ecr list-images`). Tags like `v1.4.2` are not produced by
  Fjall builds and will not resolve.
</Note>

## Understanding Output

### Success output

```bash theme={null}
Deployment complete

Outputs:
  LoadBalancerURL: http://api-123456.us-east-1.elb.amazonaws.com
  DatabaseEndpoint: api-db.cluster-abc123.us-east-1.rds.amazonaws.com

Your application is now live.
```

### Progress indicators

```bash theme={null}
ApiStack | 0/12 | 10:45:23 AM | REVIEW_IN_PROGRESS
ApiStack | 2/12 | 10:45:45 AM | CREATE_IN_PROGRESS | AWS::EC2::VPC
ApiStack | 4/12 | 10:46:12 AM | CREATE_IN_PROGRESS | AWS::RDS::DBCluster
ApiStack | 12/12 | 10:52:33 AM | CREATE_COMPLETE
```

## Handling Failures

### Common issues

1. **Permission denied**

   ```bash theme={null}
   User does not have permission to create IAM roles
   ```

   **Fix**: Give your AWS user `AdministratorAccess`.

2. **Resource already exists**

   ```bash theme={null}
   Stack with id ApiStack already exists
   ```

   **Fix**: Run `fjall destroy` first, or choose a different name.

3. **Invalid credentials**
   ```bash theme={null}
   Unable to locate credentials
   ```
   **Fix**: Run `fjall connect` to re-establish your AWS connection, or `fjall login` to re-authenticate with Fjall.

### Recovery steps

If a deployment fails:

1. **Read the error** for the specific failure message.
2. **Check CloudFormation** in the AWS Console for stack-level detail.
3. **Roll back if needed** (CloudFormation auto-rolls-back on failure).
4. **Fix and retry** once you have addressed the issue.

## Exit Codes

| Code | Meaning                                                                                                                                                                                                                                                |
| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `0`  | Deployed, or nothing to change                                                                                                                                                                                                                         |
| `1`  | A real error                                                                                                                                                                                                                                           |
| `2`  | Plan pending approval, or rejected at the approval gate (`--plan` / `--require-approval`)                                                                                                                                                              |
| `4`  | The [destruction ceremony](/deployment/destructive-changes) stopped the deploy: consent withheld, declined, invalid, not yet executable, or a consented `pin` was applied and the deploy stopped for the config write-back. Nothing was applied to AWS |
| `64` | A prerequisite is missing (Docker buildx)                                                                                                                                                                                                              |

## Best Practices

1. **Review changes** before confirming the deployment preview.
2. **Deploy incrementally**, starting with non-production targets.
3. **Use verbose mode** (`-v`) for troubleshooting.
4. **Back up data** before major changes.

## Next Steps

<CardGroup cols={2}>
  <Card title="List resources" icon="list" href="/cli/list">
    Inspect the resources in an application's infrastructure.
  </Card>

  <Card title="Add resources" icon="plus" href="/cli/add">
    Add a database, storage, or compute resource.
  </Card>

  <Card title="Manage secrets" icon="key" href="/cli/secrets">
    Store and read application secrets in AWS.
  </Card>

  <Card title="Understanding Profiles" icon="user-gear" href="/deployment/understanding-profiles">
    See how auth and account selection are derived.
  </Card>
</CardGroup>

<Note>
  First deployment typically takes 10-15 minutes. Subsequent updates are faster as only changed resources are modified.
</Note>
