> ## 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.

# Metadata Implementation

> Technical details of how Graph Node stores and manages metadata for subgraphs and deployments

## Overview

Graph Node maintains metadata across multiple database tables to track subgraphs, their deployments, and sync state. This metadata is distributed between the primary database and sharded databases to optimize for both consistency and performance.

<Note>
  Most metadata tables are maintained in the primary shard but are periodically copied to other shards to ensure query availability even when the primary is down.
</Note>

## Mapping Subgraph Names to Deployments

### subgraphs.subgraph

List of all known subgraph names. Maintained in the primary, with background jobs periodically copying the table to all other shards for query resilience.

<Accordion title="Table Schema">
  | Column            | Type         | Use                                       |
  | ----------------- | ------------ | ----------------------------------------- |
  | `id`              | `text!`      | primary key, UUID                         |
  | `name`            | `text!`      | user-chosen name                          |
  | `current_version` | `text`       | `subgraph_version.id` for current version |
  | `pending_version` | `text`       | `subgraph_version.id` for pending version |
  | `created_at`      | `numeric!`   | UNIX timestamp                            |
  | `vid`             | `int8!`      | unused                                    |
  | `block_range`     | `int4range!` | unused                                    |
</Accordion>

The `id` is used by the hosted explorer to reference the subgraph.

### subgraphs.subgraph\_version

Mapping of subgraph names to IPFS hashes. Also maintained in the primary with periodic copies to other shards.

<Accordion title="Table Schema">
  | Column        | Type         | Use                     |
  | ------------- | ------------ | ----------------------- |
  | `id`          | `text!`      | primary key, UUID       |
  | `subgraph`    | `text!`      | `subgraph.id`           |
  | `deployment`  | `text!`      | IPFS hash of deployment |
  | `created_at`  | `numeric`    | UNIX timestamp          |
  | `vid`         | `int8!`      | unused                  |
  | `block_range` | `int4range!` | unused                  |
</Accordion>

## Deployment Management

### public.deployment\_schemas

Directory of all deployments. Maintained in the primary with background job copies to other shards.

<Accordion title="Table Schema">
  | Column       | Type           | Use                                          |
  | ------------ | -------------- | -------------------------------------------- |
  | `id`         | `int4!`        | primary key                                  |
  | `subgraph`   | `text!`        | IPFS hash of deployment                      |
  | `name`       | `text!`        | name of `sgdNNN` schema                      |
  | `version`    | `int4!`        | version of data layout in `sgdNNN`           |
  | `shard`      | `text!`        | database shard holding data                  |
  | `network`    | `text!`        | network/chain used                           |
  | `active`     | `boolean!`     | whether to query this copy of the deployment |
  | `created_at` | `timestamptz!` |                                              |
</Accordion>

<Note>
  There can be multiple copies of the same deployment, but at most one per shard. The `active` flag indicates which copy will be used for queries. Graph Node ensures exactly one active copy exists for each IPFS hash.
</Note>

### subgraphs.head

Details about a deployment that change on every block. Maintained in the shard alongside the deployment's data in `sgdNNN`.

<Accordion title="Table Schema">
  | Column            | Type       | Use                                          |
  | ----------------- | ---------- | -------------------------------------------- |
  | `id`              | `integer!` | primary key, same as `deployment_schemas.id` |
  | `block_hash`      | `bytea`    | current subgraph head                        |
  | `block_number`    | `numeric`  |                                              |
  | `entity_count`    | `numeric!` | total number of entities                     |
  | `firehose_cursor` | `text`     |                                              |
</Accordion>

<Note>
  The head block pointer (`block_number` and `block_hash`) represents the latest fully processed block. It remains `null` until the deployment processes its first block. For grafted or copied deployments, the head stays `null` until the graft/copy completes, which can take considerable time.
</Note>

### subgraphs.deployment

Tracks sync progress and deployment details. Maintained in the shard alongside the deployment's data.

<Accordion title="Table Schema">
  | Column                               | Type          | Use                                                  |
  | ------------------------------------ | ------------- | ---------------------------------------------------- |
  | `id`                                 | `integer!`    | primary key, same as `deployment_schemas.id`         |
  | `subgraph`                           | `text!`       | IPFS hash                                            |
  | `earliest_block_number`              | `integer!`    | earliest block for which we have data                |
  | `health`                             | `health!`     |                                                      |
  | `failed`                             | `boolean!`    |                                                      |
  | `fatal_error`                        | `text`        |                                                      |
  | `non_fatal_errors`                   | `text[]`      |                                                      |
  | `graft_base`                         | `text`        | IPFS hash of graft base                              |
  | `graft_block_hash`                   | `bytea`       | graft block                                          |
  | `graft_block_number`                 | `numeric`     |                                                      |
  | `reorg_count`                        | `integer!`    |                                                      |
  | `current_reorg_depth`                | `integer!`    |                                                      |
  | `max_reorg_depth`                    | `integer!`    |                                                      |
  | `last_healthy_ethereum_block_hash`   | `bytea`       |                                                      |
  | `last_healthy_ethereum_block_number` | `numeric`     |                                                      |
  | `debug_fork`                         | `text`        |                                                      |
  | `synced_at`                          | `timestamptz` | time when deployment first reach chain head          |
  | `synced_at_block_number`             | `integer`     | block number where deployment first reach chain head |
</Accordion>

The reorg-related columns (`reorg_count`, `current_reorg_depth`, `max_reorg_depth`) are set during indexing to determine whether a reorg happened during query execution and if it could have affected the query results.

### subgraphs.subgraph\_manifest

Stores deployment details that rarely change. Maintained in the shard alongside deployment data.

<Accordion title="Table Schema">
  | Column                  | Type       | Use                                                  |
  | ----------------------- | ---------- | ---------------------------------------------------- |
  | `id`                    | `integer!` | primary key, same as `deployment_schemas.id`         |
  | `spec_version`          | `text!`    |                                                      |
  | `description`           | `text`     |                                                      |
  | `repository`            | `text`     |                                                      |
  | `schema`                | `text!`    | GraphQL schema                                       |
  | `features`              | `text[]!`  |                                                      |
  | `graph_node_version_id` | `integer`  |                                                      |
  | `use_bytea_prefix`      | `boolean!` |                                                      |
  | `start_block_hash`      | `bytea`    | Parent of the smallest start block from the manifest |
  | `start_block_number`    | `int4`     |                                                      |
  | `on_sync`               | `text`     | Additional behavior when deployment becomes synced   |
  | `history_blocks`        | `int4!`    | How many blocks of history to keep                   |
</Accordion>

## Additional Metadata Tables

### subgraphs.subgraph\_deployment\_assignment

Tracks which index node is indexing each deployment. Maintained in the primary with periodic copies to other shards.

<Accordion title="Table Schema">
  | Column   | Type  | Use                                         |
  | -------- | ----- | ------------------------------------------- |
  | id       | int4! | primary key, ref to `deployment_schemas.id` |
  | node\_id | text! | name of index node                          |
</Accordion>

<Note>
  This table could simply be a column on `deployment_schemas`.
</Note>

### subgraphs.dynamic\_ethereum\_contract\_data\_source

Stores dynamic data sources for all subgraphs.

<Note>
  This table will soon be moved into each subgraph's namespace (`sgdNNN`).
</Note>

### subgraphs.subgraph\_error

Stores details about errors encountered during indexing.

### Deployment Copying

The following tables track deployment copying progress:

* `active_copies` (in primary)
* `subgraphs.copy_state`
* `subgraphs.copy_table_state`

These ensure copying works correctly across index node restarts.

### subgraphs.table\_stats

Stores information about which tables should have the 'account-like' optimization enabled for query generation.

### subgraphs.subgraph\_features

Details about features used by deployments. Maintained in the primary.

<Accordion title="Table Schema">
  | Column         | Type      | Use         |
  | -------------- | --------- | ----------- |
  | `id`           | `text!`   | primary key |
  | `spec_version` | `text!`   |             |
  | `api_version`  | `text`    |             |
  | `features`     | `text[]!` |             |
  | `data_sources` | `text[]!` |             |
  | `handlers`     | `text[]!` |             |
</Accordion>

## Metadata Distribution Strategy

<CodeGroup>
  ```text Primary Shard theme={null}
  - subgraphs.subgraph
  - subgraphs.subgraph_version
  - public.deployment_schemas
  - subgraphs.subgraph_deployment_assignment
  - subgraphs.subgraph_features
  ```

  ```text Deployment Shard (sgdNNN) theme={null}
  - subgraphs.head
  - subgraphs.deployment
  - subgraphs.subgraph_manifest
  - Entity tables
  ```

  ```text Replicated to All Shards theme={null}
  - subgraphs.subgraph (copy)
  - subgraphs.subgraph_version (copy)
  - public.deployment_schemas (copy)
  - subgraphs.subgraph_deployment_assignment (copy)
  ```
</CodeGroup>

This distribution strategy ensures that:

1. Critical routing information is available on all shards
2. Queries can be served even when the primary shard is unavailable
3. Frequently changing data stays close to the deployment data
4. Background jobs keep replicated data synchronized
