---
name: thyme-migrate-goldsky
description: Move subgraphs from Goldsky (or Alchemy Subgraphs) to Thyme Atlas, the hosted Graph Node service. Use when a repository deploys with `goldsky subgraph deploy`, queries `api.goldsky.com` subgraph endpoints, or the user asks to move subgraphs to Atlas. Covers checking manifests against Atlas limits, deploying the same build with Graph CLI, verifying sync, and switching application endpoints without downtime.
---

# Migrate subgraphs from Goldsky to Thyme Atlas

Thyme Atlas runs standard subgraphs on managed Graph Nodes. The same
`subgraph.yaml`, schema and mappings deploy with Graph CLI, so a move is a
redeploy, a sync, and an endpoint swap. Goldsky keeps serving until the switch,
so there is no downtime. The same steps apply to subgraphs that came from
Alchemy Subgraphs, which shut down on December 8, 2025.

Atlas documentation: `https://flow.thymelabs.io/docs/atlas/quickstart`,
`/docs/atlas/networks` and `/docs/atlas/queries` on the same host.

## Rules

1. **Never print, log or commit keys.** Deployment keys start with
   `atlas_dk_`, query keys with `atlas_qk_`. Read them from environment
   variables the user sets.
2. **A person creates keys and promotes releases** in the Atlas console
   (`https://atlas.thymelabs.io`). Ask the user to do it and to export the key.
3. **Do not touch the Goldsky deployment** until the user confirms traffic has
   moved. Deleting it is the user's decision.
4. **Ask before changing application endpoints** in code that ships to
   production.

## 1. Inventory

```bash
find . -name 'subgraph.yaml' -not -path '*/node_modules/*'
grep -rn --exclude-dir=node_modules -e 'goldsky subgraph' -e 'api.goldsky.com' -e 'satsuma' .
```

For each subgraph, list its directory, the networks in its manifest, the
Goldsky name and version (from deploy scripts or CI), and every place the
application queries it (URLs, environment variables, `.graphclientrc.yml`,
Apollo or urql clients).

## 2. Check each manifest against Atlas

Atlas validates the manifest after the upload, so check first:

| Check | Atlas rule |
|---|---|
| `network` | One of `mainnet`, `sepolia`, `matic` (also `polygon`, `matic-mainnet`), `polygon-amoy`, `optimism`, `bsc`, `unichain-testnet`. One network per subgraph. |
| `specVersion` | Up to `1.5.0`. |
| Mapping `apiVersion` | Up to `0.0.10`. |
| Data source `kind` | `ethereum` or `ethereum/contract`. Templates are supported. |
| Handlers | Event, block and call handlers. Call handlers need traces; Atlas warns. |
| Not supported | Grafting (`graft:`), file data sources, `ipfsOnEthereumContracts`, Substreams. |
| `indexerHints.prune` | Unset, `auto`, or a number from 500 up to the network's limit (about one day of blocks). `never` is rejected. |
| `optimism` | Every `startBlock` at least 105,235,064 (Bedrock). |
| Size | 1 to 128 data sources, up to 128 templates, up to 256 files, manifest up to 1 MiB, any file up to 25 MiB, whole deployment up to 100 MiB. |

Report every subgraph that fails a rule and why, and do not deploy it. If the
application relies on more than about a day of time-travel queries
(`block: { number: … }`), say that Atlas keeps at most about one day of
history.

## 3. Deploy to Atlas

Ask the user to create a **deployment key** on the Atlas console's Keys page
and export it as `ATLAS_DEPLOY_KEY`. Then, from the subgraph directory:

```bash
graph create <name> \
  --node https://deploy.atlas.thymelabs.io \
  --access-token "$ATLAS_DEPLOY_KEY"

graph codegen
graph build

graph deploy <name> \
  --node https://deploy.atlas.thymelabs.io/ \
  --ipfs https://ipfs.atlas.thymelabs.io/api/v0 \
  --deploy-key "$ATLAS_DEPLOY_KEY" \
  --headers "{\"Authorization\":\"Bearer $ATLAS_DEPLOY_KEY\"}" \
  --version-label v1
```

- `graph create` runs once per name. A deploy to a missing name fails with
  `Create this subgraph in Atlas or with graph create first`.
- Keep `--headers`: it authenticates the file uploads.
- Version labels are immutable. Use a new label for every deploy.
- If the deployment is already published on The Graph, the user can instead
  use **Import from The Graph** in the console with its deployment ID.
- Add the Atlas deploy as a script next to the Goldsky one (for example
  `deploy:atlas` in `package.json`) instead of replacing it, until the switch.

## 4. Verify sync, then promote

Ask the user for a **query key** exported as `ATLAS_QUERY_KEY`, and the
subgraph ID and version ID from the console or the deploy output. Query the
release before it is promoted:

```bash
curl -s https://query.atlas.thymelabs.io/subgraphs/<subgraph-id>/versions/<version-id> \
  -H "Authorization: Bearer $ATLAS_QUERY_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"query":"{ _meta { block { number } hasIndexingErrors } }"}'
```

When the block number is close to the chain head and `hasIndexingErrors` is
false, compare a few real queries against the Goldsky endpoint at the same
block. Then ask the user to **promote** the release in the console. The
production URL `https://query.atlas.thymelabs.io/subgraphs/<subgraph-id>`
returns 403 until a release is promoted.

## 5. Switch the application

Atlas needs a key on every query: `Authorization: Bearer <key>` or
`X-API-Key: <key>`. Goldsky public endpoints needed none, so add the header.

| Client | Change |
|---|---|
| `fetch` | Add `Authorization: 'Bearer ' + key` to the headers. |
| Apollo | `new HttpLink({ uri, headers: { Authorization: 'Bearer ' + key } })` |
| urql | `fetchOptions: { headers: { Authorization: 'Bearer ' + key } }` |
| Graph Client | Set the source `endpoint` and `operationHeaders` in `.graphclientrc.yml`. |

Read the URL and key from configuration (environment variables), not literals.
A key used from a browser is visible to everyone: tell the user to restrict it
on the console's Keys page to their origins, and to one subgraph if they like.
Limits per query key are 16 requests in flight and 150 per second.

## 6. Report back

For every subgraph, tell the user: manifest check results, the Atlas name and
version label, sync status, the code you changed for the endpoint, and what
they must still do (create keys, promote the release, restrict browser keys,
switch production configuration, and delete the Goldsky deployment once
traffic has moved so it stops using worker hours).
