## TL;DR

Fly deploys need to place Machines in a region, and the region can refuse: capacity constraints, a region that does not support the app's requirements, or an org-level region allowlist. Check region status, try a nearby region, and make the region choice explicit and documented instead of defaulted.

## The query

```text
fly deploy failed: 'no machines available in region'
```

## Use this when

- `fly deploy` fails naming machine availability in a region.
- The app deployed fine to this region before.
- The failure is intermittent across deploys.

## Not for

- Build failures (fix the Dockerfile/build).
- Machines that start then crash (application bug).
- `fly.toml` config errors (config problem).

## Steps

### Step 1: Check the region's status

```bash
fly regions list -a [app]
fly status -a [app]
```

Expected result: you see the configured regions and current machine placement. The failing region is named explicitly.

### Step 2: Try a nearby region

Add a neighboring region to the region list and redeploy.

```bash
fly regions add [nearby-region] -a [app]
fly deploy -a [app]
```

Expected result: machines place successfully in the new region. This unblocks the deploy while the original region recovers.

### Step 3: Check capacity and quotas

Org-level machine limits and region-specific capacity can both refuse placement. The dashboard shows quota usage.

Expected result: you know whether the refusal is capacity (wait or request more) or policy (allowlist, region support).

### Step 4: Make regions explicit in fly.toml

```toml
[env]
  PRIMARY_REGION = "[region]"
```

Expected result: the region choice is deliberate and documented. 'Default region' behavior is what made the failure surprising.

### Step 5: Verify placement and health

```bash
fly status -a [app]
```

Expected result: machines are running in the intended regions and passing health checks.

## Why it happens

Machine placement is a scheduling decision with real constraints: physical capacity, region capabilities, and org policy. Deploys assume placement always succeeds, so the first refusal looks like a deploy bug. It is a capacity signal, and the fix is placement flexibility, not deploy retries.

## Edge cases

- Retrying the same region immediately usually fails the same way. Back off or move regions.
- Volumes pin machines to regions. An app with volumes cannot freely move; plan volume regions deliberately.
- Multi-region deploys can partially succeed. Check every region, not just the first.
- Scale-to-zero apps hit this on cold wake too, not just on deploy.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_6UHGyAOg-4u-Mz7ykxkbZg
