TL;DR: Do not re-run the whole thing. Rails records each finished migration in the schema_migrations table before moving on, so a killed run can be resumed: check which migrations already applied, give the next attempt a longer timeout, then run db:migrate again and it picks up where it stopped. Only the interrupted migration itself needs care.

```text
agent ran rails db:migrate under a 5-minute tool timeout but the migration itself takes 20 - how to resume without re-running from scratch
```

1. Find out exactly where the run died: run `rails db:migrate:status`.
   Expected: a list where applied migrations show "up" and the rest show "down"; the first "down" after a run of "up" is where the kill happened.
2. Check whether the killed migration left a half-applied state: read the migration file for the first "down" version and check whether its DDL is transactional in your database.
   Expected: on Postgres, DDL inside a migration runs in a transaction, so a killed migration rolls back cleanly; on MySQL, DDL is not transactional, so inspect the table for a partial change.
3. Raise the timeout for the resume attempt: give the migrate step a timeout longer than the longest single migration, or run the long migration in the background and poll it.
   Expected: the harness no longer kills the step before the 20-minute migration finishes.
4. Resume with plain `rails db:migrate`.
   Expected: output shows only the remaining migrations applying, and ends with no errors.
5. Verify the final state: run `rails db:migrate:status` again and confirm every migration shows "up".
   Expected: no "down" rows remain.

## Use this when
- db:migrate was killed by a tool or step timeout before finishing
- you need to continue a long migration run without replaying applied migrations
- the agent harness imposes a step timeout shorter than a migration's runtime

## Not for this skill when
- the migration failed with an actual error (not a timeout kill) - fix the error first
- migrations were edited after being applied (state mismatch)
- you are trying to roll back, not resume forward

## Variant phrasings
- rails migration killed by timeout, how to continue from where it stopped
- db:migrate timed out halfway, resume remaining migrations
- long rails migration versus short agent step timeout

## Why it happens
Rails tracks applied migrations one row at a time in schema_migrations. A timeout kill is an external interruption, not a migration failure: everything committed before the kill is recorded, and db:migrate always starts from the current recorded version. Re-running from scratch is unnecessary because migrate is incremental by design - the agent just needs to confirm where the recorded state ends and re-run with a timeout that fits.

## Edge cases
- If the killed migration was mid-DDL on MySQL, part of it may have applied with no schema_migrations row. Inspect the actual schema before re-running, or the resume fails on "already exists".
- statement_timeout on Postgres can kill a long migration even when the harness timeout is fine - check the log for a query-canceled error and raise the database timeout too.
- Running two migrates at once after a resume (a retry loop plus a manual run) can double-apply on databases without advisory-lock protection - make sure only one migrate runs at a time.
- A migration that takes 20 minutes on a big table is a sign to rewrite it (concurrent index creation, batched backfill) rather than raising timeouts forever.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_Ygf3YTZ1GflvgQgz-G4G_A
