> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/graphprotocol/graph-node/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploying Subgraphs

> Learn how to deploy and manage subgraphs on Graph Node

This guide covers the complete workflow for deploying subgraphs to a Graph Node instance, from development to production.

## Prerequisites

Before deploying a subgraph, ensure you have:

1. A running Graph Node instance
2. PostgreSQL database configured and accessible
3. IPFS node running and accessible
4. An Ethereum node or provider endpoint
5. Graph CLI or GND installed

## Installation

<Tabs>
  <Tab title="Graph CLI">
    ```bash theme={null}
    npm install -g @graphprotocol/graph-cli
    # or
    yarn global add @graphprotocol/graph-cli
    ```
  </Tab>

  <Tab title="GND (Rust)">
    ```bash theme={null}
    cargo install --git https://github.com/graphprotocol/graph-node gnd
    ```
  </Tab>
</Tabs>

## Setting Up Graph Node

### Using Docker Compose

The quickest way to get started is using Docker Compose:

<CodeGroup>
  ```bash Start Graph Node theme={null}
  # Clone the repository
  git clone https://github.com/graphprotocol/graph-node
  cd graph-node/docker

  # Start all services
  docker-compose up
  ```

  ```yaml docker-compose.yaml theme={null}
  version: '3'
  services:
    graph-node:
      image: graphprotocol/graph-node
      ports:
        - '8000:8000'
        - '8001:8001'
        - '8020:8020'
        - '8030:8030'
        - '8040:8040'
      depends_on:
        - ipfs
        - postgres
      environment:
        postgres_host: postgres
        postgres_user: graph-node
        postgres_pass: let-me-in
        postgres_db: graph-node
        ipfs: 'ipfs:5001'
        ethereum: 'mainnet:http://host.docker.internal:8545'
        GRAPH_LOG: info
    ipfs:
      image: ipfs/kubo:v0.14.0
      ports:
        - '5001:5001'
      volumes:
        - ./data/ipfs:/data/ipfs
    postgres:
      image: postgres:14
      ports:
        - '5432:5432'
      command:
        [
          "postgres",
          "-cshared_preload_libraries=pg_stat_statements",
          "-cmax_connections=200"
        ]
      environment:
        POSTGRES_USER: graph-node
        POSTGRES_PASSWORD: let-me-in
        POSTGRES_DB: graph-node
      volumes:
        - ./data/postgres:/var/lib/postgresql/data
  ```
</CodeGroup>

This starts:

* **Graph Node** on `http://localhost:8000` (GraphQL HTTP)
* **IPFS** on `http://localhost:5001`
* **PostgreSQL** on `localhost:5432`
* **Admin API** on `http://localhost:8020`

### Running from Source

<CodeGroup>
  ```bash Build and Run theme={null}
  # Install dependencies
  sudo apt-get install -y postgresql postgresql-contrib libpq-dev

  # Create database
  psql -U postgres <<EOF
  create user graph with password 'password';
  create database "graph-node" with owner=graph template=template0 encoding='UTF8' locale='C';
  \c graph-node
  create extension pg_trgm;
  create extension btree_gist;
  create extension postgres_fdw;
  grant usage on foreign data wrapper postgres_fdw to graph;
  EOF

  # Set environment variable
  export POSTGRES_URL=postgresql://graph:password@localhost:5432/graph-node

  # Build and run
  export GRAPH_LOG=debug
  cargo run -p graph-node --release -- \
    --postgres-url $POSTGRES_URL \
    --ethereum-rpc mainnet:archive,traces:https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY \
    --ipfs 127.0.0.1:5001
  ```
</CodeGroup>

### Using Existing Services

If you already have IPFS and PostgreSQL running:

<CodeGroup>
  ```bash Run with Existing Services theme={null}
  docker run -it \
    -e postgres_host=<HOST> \
    -e postgres_port=<PORT> \
    -e postgres_user=<USER> \
    -e postgres_pass=<PASSWORD> \
    -e postgres_db=<DBNAME> \
    -e ipfs=<HOST>:<PORT> \
    -e ethereum=<NETWORK_NAME>:<ETHEREUM_RPC_URL> \
    graphprotocol/graph-node:latest
  ```
</CodeGroup>

## Creating a Subgraph

### Initialize Project

<CodeGroup>
  ```bash Create Subgraph theme={null}
  # Initialize a new subgraph
  graph init --product hosted-service myorg/my-subgraph

  # Or from an existing contract
  graph init \
    --product hosted-service \
    --from-contract 0x1234567890123456789012345678901234567890 \
    --network mainnet \
    myorg/my-subgraph
  ```
</CodeGroup>

This creates a project structure:

```
my-subgraph/
├── abis/
│   └── Contract.json
├── src/
│   └── mapping.ts
├── schema.graphql
├── subgraph.yaml
└── package.json
```

### Define Schema

Edit `schema.graphql` to define your data model:

<CodeGroup>
  ```graphql schema.graphql theme={null}
  type User @entity {
    id: ID!
    address: Bytes!
    transactions: [Transaction!]! @derivedFrom(field: "user")
    totalVolume: BigInt!
    createdAt: BigInt!
  }

  type Transaction @entity {
    id: ID!
    user: User!
    amount: BigInt!
    timestamp: BigInt!
    blockNumber: BigInt!
  }
  ```
</CodeGroup>

### Configure Manifest

Edit `subgraph.yaml` to configure your data sources:

<CodeGroup>
  ```yaml subgraph.yaml theme={null}
  specVersion: 0.0.8
  schema:
    file: ./schema.graphql
  dataSources:
    - kind: ethereum/contract
      name: MyContract
      network: mainnet
      source:
        address: "0x1234567890123456789012345678901234567890"
        abi: MyContract
        startBlock: 12345678
      mapping:
        kind: ethereum/events
        apiVersion: 0.0.7
        language: wasm/assemblyscript
        entities:
          - User
          - Transaction
        abis:
          - name: MyContract
            file: ./abis/MyContract.json
        eventHandlers:
          - event: Transfer(indexed address,indexed address,uint256)
            handler: handleTransfer
        file: ./src/mapping.ts
  ```
</CodeGroup>

### Write Mappings

Implement event handlers in `src/mapping.ts`:

<CodeGroup>
  ```typescript src/mapping.ts theme={null}
  import { Transfer } from '../generated/MyContract/MyContract'
  import { User, Transaction } from '../generated/schema'
  import { BigInt } from '@graphprotocol/graph-ts'

  export function handleTransfer(event: Transfer): void {
    // Load or create user
    let user = User.load(event.params.to.toHex())
    if (!user) {
      user = new User(event.params.to.toHex())
      user.address = event.params.to
      user.totalVolume = BigInt.fromI32(0)
      user.createdAt = event.block.timestamp
    }
    
    user.totalVolume = user.totalVolume.plus(event.params.value)
    user.save()
    
    // Create transaction
    let transaction = new Transaction(event.transaction.hash.toHex())
    transaction.user = user.id
    transaction.amount = event.params.value
    transaction.timestamp = event.block.timestamp
    transaction.blockNumber = event.block.number
    transaction.save()
  }
  ```
</CodeGroup>

## Building the Subgraph

Generate types and compile the subgraph:

<CodeGroup>
  ```bash Build Commands theme={null}
  # Install dependencies
  npm install

  # Generate types from schema and ABIs
  graph codegen

  # Build the subgraph
  graph build
  ```
</CodeGroup>

<ParamField path="codegen" type="command">
  Generates AssemblyScript types from the GraphQL schema and contract ABIs.
</ParamField>

<ParamField path="build" type="command">
  Compiles the subgraph to WebAssembly and prepares it for deployment.
</ParamField>

## Deploying the Subgraph

### Create Subgraph

First, create the subgraph on your Graph Node:

<CodeGroup>
  ```bash Create Subgraph theme={null}
  # Create the subgraph
  graph create --node http://localhost:8020 myorg/my-subgraph
  ```
</CodeGroup>

### Deploy

Deploy your subgraph to the Graph Node:

<CodeGroup>
  ```bash Deploy Subgraph theme={null}
  # Deploy to local node
  graph deploy --node http://localhost:8020 --ipfs http://localhost:5001 myorg/my-subgraph

  # With version label
  graph deploy --node http://localhost:8020 --ipfs http://localhost:5001 myorg/my-subgraph --version-label v0.1.0
  ```
</CodeGroup>

The deployment process:

1. Uploads files to IPFS
2. Creates deployment with unique ID
3. Starts indexing from `startBlock`
4. Makes subgraph available for querying

## Querying the Subgraph

Once deployed, you can query your subgraph:

<Tabs>
  <Tab title="GraphQL Playground">
    Navigate to `http://localhost:8000/subgraphs/name/myorg/my-subgraph` to access the GraphQL playground.
  </Tab>

  <Tab title="HTTP Query">
    ```bash theme={null}
    curl -X POST \
      -H "Content-Type: application/json" \
      -d '{"query": "{ users(first: 5) { id address totalVolume } }" }' \
      http://localhost:8000/subgraphs/name/myorg/my-subgraph
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    const query = `
      query {
        users(first: 5, orderBy: totalVolume, orderDirection: desc) {
          id
          address
          totalVolume
          transactions(first: 10) {
            amount
            timestamp
          }
        }
      }
    `

    const response = await fetch('http://localhost:8000/subgraphs/name/myorg/my-subgraph', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ query })
    })

    const data = await response.json()
    console.log(data.data.users)
    ```
  </Tab>
</Tabs>

## Managing Deployments

### Check Status

<CodeGroup>
  ```bash Query Indexing Status theme={null}
  curl -X POST \
    -H "Content-Type: application/json" \
    -d '{"query": "{ indexingStatuses { subgraph synced health fatalError { message } chains { network latestBlock { number } chainHeadBlock { number } } } }" }' \
    http://localhost:8000/graphql
  ```
</CodeGroup>

### Remove Subgraph

<CodeGroup>
  ```bash Remove Subgraph theme={null}
  graph remove --node http://localhost:8020 myorg/my-subgraph
  ```
</CodeGroup>

### Reassign Subgraph

Move a subgraph to a different node:

<CodeGroup>
  ```bash Reassign to Node theme={null}
  graphman --config config.toml reassign myorg/my-subgraph node-id-2
  ```
</CodeGroup>

## Environment Variables

Key environment variables for deployment:

<ParamField path="GRAPH_LOG" type="String" default="info">
  Control log levels. Options: `error`, `warn`, `info`, `debug`, `trace`
</ParamField>

<ParamField path="ETHEREUM_REORG_THRESHOLD" type="Number" default="250">
  Maximum expected reorg size. Larger reorgs may cause inconsistent data.
</ParamField>

<ParamField path="ETHEREUM_POLLING_INTERVAL" type="Number" default="500">
  How often to poll Ethereum for new blocks (in milliseconds).
</ParamField>

<ParamField path="GRAPH_ETHEREUM_TARGET_TRIGGERS_PER_BLOCK_RANGE" type="Number" default="100">
  The ideal amount of triggers to be processed in a batch.
</ParamField>

<ParamField path="GRAPH_IPFS_TIMEOUT" type="Number" default="60">
  Timeout for IPFS requests in seconds.
</ParamField>

<ParamField path="GRAPH_GRAPHQL_QUERY_TIMEOUT" type="Number">
  Maximum execution time for a GraphQL query in seconds. Default is unlimited.
</ParamField>

<ParamField path="GRAPH_KILL_IF_UNRESPONSIVE" type="Boolean" default="false">
  If set, the process will be killed if unresponsive.
</ParamField>

## Troubleshooting

<Tabs>
  <Tab title="Connection Issues">
    **Problem:** Graph Node can't connect to Ethereum

    **Solutions:**

    * Verify RPC endpoint is accessible
    * Check network name matches (e.g., `mainnet` not `ethereum`)
    * Ensure provider has required capabilities (archive, traces)
    * Test connection: `curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' YOUR_RPC_URL`
  </Tab>

  <Tab title="Sync Issues">
    **Problem:** Subgraph not syncing or syncing slowly

    **Solutions:**

    * Check `startBlock` is set appropriately
    * Verify `ETHEREUM_POLLING_INTERVAL` isn't too high
    * Check logs for errors: `docker logs graph-node`
    * Ensure database has sufficient resources
    * Monitor block processing: Query `indexingStatuses` endpoint
  </Tab>

  <Tab title="Deployment Failures">
    **Problem:** Deployment fails or shows errors

    **Solutions:**

    * Run `graph build` to check for compilation errors
    * Verify all ABIs are valid JSON
    * Check event signatures match contract exactly
    * Ensure `specVersion` matches features used
    * Review mapping handler logic for runtime errors
  </Tab>

  <Tab title="Query Errors">
    **Problem:** GraphQL queries fail or timeout

    **Solutions:**

    * Simplify query to isolate issue
    * Add pagination with `first` and `skip`
    * Check query complexity isn't too high
    * Set `GRAPH_GRAPHQL_MAX_COMPLEXITY` if needed
    * Review entity relationships for N+1 issues
  </Tab>
</Tabs>

## Best Practices

<Tabs>
  <Tab title="Development">
    1. **Test locally first** - Always test with a local Graph Node before deploying to production
    2. **Use version labels** - Tag deployments with semantic versions for tracking
    3. **Start small** - Begin with a limited block range, then expand
    4. **Monitor resources** - Watch CPU, memory, and disk usage during indexing
    5. **Handle errors gracefully** - Use try-catch in mappings and check for null values
  </Tab>

  <Tab title="Performance">
    1. **Set appropriate startBlock** - Don't index from genesis if not needed
    2. **Optimize queries** - Avoid deeply nested queries and use pagination
    3. **Use entity loading efficiently** - Load entities once and reuse
    4. **Batch operations** - Group related operations together
    5. **Monitor indexing speed** - Track blocks per second and adjust resources
  </Tab>

  <Tab title="Production">
    1. **Use archive nodes** - Required for historical state queries
    2. **Enable tracing** - If using call handlers
    3. **Set up monitoring** - Track indexing status and query performance
    4. **Plan for reorgs** - Set appropriate `ETHEREUM_REORG_THRESHOLD`
    5. **Back up data** - Regularly backup PostgreSQL database
    6. **Use redundant providers** - Configure multiple RPC endpoints
  </Tab>
</Tabs>

## Next Steps

* Learn about [multi-network deployments](/deployment/multiple-networks)
* Review the [subgraph manifest specification](/deployment/subgraph-manifest)
* Explore [advanced configuration](/configuration/advanced-config)
* Set up [monitoring and metrics](/operations/monitoring)
