## TL;DR

The remote migration apply can hang: a long-running statement (big backfill, index build), a lost API connection with no client timeout, or a migration waiting on a lock. The agent cannot tell 'slow' from 'stuck'. Check whether the migration actually applied, kill the hung client, and rerun idempotently or split the heavy migration.

## The query

```text
agent timed out waiting for D1 migration to apply on remote: wrangler hung after 'applying migration'
```

## Use this when

- `wrangler d1 migrations apply --remote` hangs after 'applying migration'.
- The agent timed out with unknown migration state.
- It worked for small migrations and hangs for big ones.

## Not for

- Migration SQL errors (fix the SQL).
- 'migration table already exists' (journal problem, separate fix).
- Local apply hangs (different path).

## Steps

### Step 1: Check whether the migration applied despite the hang

```bash
npx wrangler d1 migrations list [db] --remote
```

Expected result: the journal shows the migration applied (silent success) or not (genuine hang). This decides everything downstream.

### Step 2: If applied, move on

The hang was in the response path, not the migration. The schema is correct.

Expected result: no rerun, no 'fix'. Rerunning an applied migration is how journal conflicts start.

### Step 3: If not applied, inspect the migration for heavy statements

Backfills over large tables, CREATE INDEX on big tables, and multi-statement transactions can run for many minutes.

Expected result: you find the heavy statement. That is what the agent waited on.

### Step 4: Split heavy migrations

Separate schema changes (fast) from data backfills (slow). Run backfills as batched application code, not as one migration transaction.

Expected result: migrations stay fast and bounded. Slow data work happens where it can be monitored and resumed.

### Step 5: Rerun with the agent timeout matched to reality

Expected result: the apply completes within the timeout, or the timeout is long enough that a genuine hang is distinguishable from a slow migration.

## Why it happens

Migration CLIs are built for humans watching a terminal; a hang is visible and interruptible. Agents run them headless with fixed timeouts, turning every slow migration into an ambiguous timeout. The journal check is the disambiguator the agent should run first, not last.

## Edge cases

- Never Ctrl-C and immediately rerun without checking the journal. Partial applies plus reruns equal corruption risk.
- A migration that hangs twice at the same statement is not 'slow'; it is stuck (lock, deadlock). Investigate, do not extend the timeout again.
- Long migrations hold locks that block the app's writes. Schedule heavy migrations in low-traffic windows.
- The local journal does not reflect remote state. Always check --remote for remote applies.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_hm6eQt5x2BYyexCQSCa9yA
