> For the complete documentation index, see [llms.txt](https://docs.envio.dev/llms.txt).

Static, deep-linkable reference for the V3 `config.yaml` schema.

> Tip: Use the Table of Contents to jump to a field or definition.


## Top-level Properties

- [description](#description)
- [name](#name) (required)
- [ecosystem](#ecosystem)
- [schema](#schema)
- [contracts](#contracts)
- [chains](#chains) (required)
- [rollback_on_reorg](#rollbackonreorg)
- [save_full_history](#savefullhistory)
- [field_selection](#fieldselection)
- [raw_events](#rawevents)
- [address_format](#addressformat)
- [full_batch_size](#fullbatchsize)
- [storage](#storage)

### description {#description}

Description of the project

- **type**: `string | null`


Example (config.yaml):

```yaml
description: Greeter indexer
```

### name {#name}

Name of the project

- **type**: `string`


Example (config.yaml):

```yaml
name: MyIndexer
```

### ecosystem {#ecosystem}

Ecosystem of the project.

- **type**: `anyOf(object<EcosystemTag> | null)`

Variants:
- `1`: [EcosystemTag](#def-ecosystemtag)
- `2`: `null`


Example (config.yaml):

```yaml
ecosystem: evm
```

### schema {#schema}

Custom path to schema.graphql file

- **type**: `string | null`


Example (config.yaml):

```yaml
schema: ./schema.graphql
```

### contracts {#contracts}

Global contract definitions that must contain all definitions except addresses. You can share a single handler/abi/event definitions for contracts across multiple chains.

- **type**: `array | null`


Example (config.yaml):

```yaml
contracts:
  - name: Greeter
    events:
      - event: "NewGreeting(address user, string greeting)"
```

### chains {#chains}

Configuration of the blockchain chains that the project is deployed on.

- **type**: `array<object<Chain>>`
- **items**: `object<Chain>`
- **items ref**: [Chain](#def-chain)


Example (config.yaml):

```yaml
chains:
  - id: 1
    start_block: 0
    contracts:
      - name: Greeter
        address: "0x9D02A17dE4E68545d3a58D3a20BbBE0399E05c9c"
```

### rollback_on_reorg {#rollbackonreorg}

A flag to indicate if the indexer should rollback to the last known valid block on a reorg. This currently incurs a performance hit on historical sync and is recommended to turn this off while developing (default: true)

- **type**: `boolean | null`


Example (config.yaml):

```yaml
rollback_on_reorg: true
```

### save_full_history {#savefullhistory}

A flag to indicate if the indexer should save the full history of events. This is useful for debugging but will increase the size of the database (default: false)

- **type**: `boolean | null`


Example (config.yaml):

```yaml
save_full_history: false
```

### field_selection {#fieldselection}

Select the block and transaction fields to include in all events globally

- **type**: `anyOf(object<FieldSelection> | null)`

Variants:
- `1`: [FieldSelection](#def-fieldselection)
- `2`: `null`


Example (config.yaml):

```yaml
field_selection:
  transaction_fields:
    - hash
  block_fields:
    - miner
```

### raw_events {#rawevents}

If true, the indexer will store the raw event data in the database. This is useful for debugging, but will increase the size of the database and the amount of time it takes to process events (default: false)

- **type**: `boolean | null`


Example (config.yaml):

```yaml
raw_events: true
```

### address_format {#addressformat}

Address format for Ethereum addresses: 'checksum' or 'lowercase' (default: checksum)

- **type**: `anyOf(object<AddressFormat> | null)`

Variants:
- `1`: [AddressFormat](#def-addressformat)
- `2`: `null`


### full_batch_size {#fullbatchsize}

Maximum number of events processed per batch. Replaces the V2 `MAX_BATCH_SIZE` environment variable.

- **type**: `integer | null`
- **bounds**: min: 1, format: `uint32`


Example (config.yaml):

```yaml
full_batch_size: 5000
```

### storage {#storage}

Configures which storage backends the indexer writes to. Postgres is enabled by default; enable ClickHouse by setting `clickhouse: true`. When both backends are enabled, route each entity explicitly via the `@storage` directive in `schema.graphql`:

```graphql
type Transfer @storage(postgres: true, clickhouse: true) {
  id: ID!
}
```

- **type**: `anyOf(object<Storage> | null)`

Variants:
- `1`: [Storage](#def-storage)
- `2`: `null`


Example (config.yaml):

```yaml
storage:
  postgres: true
  clickhouse: true
```

## Definitions

### EcosystemTag {#def-ecosystemtag}

- **type**: `enum (1 values)`
- **allowed**: `evm`

Example (config.yaml):

```yaml
ecosystem: evm
```

### GlobalContract_for_ContractConfig {#def-globalcontractforcontractconfig}

- **type**: `object`
- **required**: `name`, `events`

Properties:
- `name`: `string` – A unique project-wide name for this contract (no spaces)
- `abi_file_path`: `string | null` – Relative path (from config) to a json abi. If this is used then each configured event should simply be referenced by its name
- `handler`: `string | null` – Optional explicit path to a handler file. If omitted, handlers are auto-discovered from `src/handlers/`.
- `events`: `array<object<EventConfig>>` – A list of events that should be indexed on this contract

Example (config.yaml):

```yaml
contracts:
  - name: Greeter
    events:
      - event: "NewGreeting(address user, string greeting)"
```

### EventConfig {#def-eventconfig}

- **type**: `object`
- **required**: `event`

Properties:
- `event`: `string` – The human readable signature of an event 'eg. Transfer(address indexed from, address indexed to, uint256 value)' OR a reference to the name of an event in a json ABI file defined in your contract config. A provided signature will take precedence over what is defined in the json ABI
- `name`: `string | null` – Name of the event in the HyperIndex generated code. When ommitted, the event field will be used. Should be unique per contract
- `field_selection`: `anyOf(object<FieldSelection> | null)` – Select the block and transaction fields to include in the specific event

Example (config.yaml):

```yaml
contracts:
  - name: Greeter
    events:
      - event: "Assigned(address indexed recipientId, uint256 amount, address token)"
        name: Assigned
        field_selection:
          transaction_fields:
            - transactionIndex
```

### FieldSelection {#def-fieldselection}

- **type**: `object`

Properties:
- `transaction_fields`: `array | null` – The transaction fields to include in the event, or in all events if applied globally
  - Available values:
`transactionIndex`, `hash`, `from`, `to`, `gas`, `gasPrice`, `maxPriorityFeePerGas`, `maxFeePerGas`, `cumulativeGasUsed`, `effectiveGasPrice`, `gasUsed`, `input`, `nonce`, `value`, `v`, `r`, `s`, `contractAddress`, `logsBloom`, `root`, `status`, `yParity`, `chainId`, `accessList`, `maxFeePerBlobGas`, `blobVersionedHashes`, `type`, `l1Fee`, `l1GasPrice`, `l1GasUsed`, `l1FeeScalar`, `gasUsedForL1`, `authorizationList`
- `block_fields`: `array | null` – The block fields to include in the event, or in all events if applied globally
  - Available values:
`parentHash`, `nonce`, `sha3Uncles`, `logsBloom`, `transactionsRoot`, `stateRoot`, `receiptsRoot`, `miner`, `difficulty`, `totalDifficulty`, `extraData`, `size`, `gasLimit`, `gasUsed`, `uncles`, `baseFeePerGas`, `blobGasUsed`, `excessBlobGas`, `parentBeaconBlockRoot`, `withdrawalsRoot`, `l1BlockNumber`, `sendCount`, `sendRoot`, `mixHash`

Example (config.yaml):

```yaml
events:
  - event: "Assigned(address indexed user, uint256 amount)"
    # can be within an event as shown here, or globally for all events
    field_selection:
      transaction_fields:
        - transactionIndex
      block_fields:
        - miner
```

### Rpc {#def-rpc}

- **type**: `object`
- **required**: `url`, `for`

Properties:
- `url`: `string` – The RPC endpoint URL. WebSocket URLs (`wss://...`) are also supported when paired with `for: realtime`.
- `for`: `object<For>` – Determines if this RPC is for historical sync (`sync`), realtime head indexing (`realtime`, supports WebSocket), or as a fallback (`fallback`).
- `initial_block_interval`: `integer | null` – The starting interval in range of blocks per query
- `backoff_multiplicative`: `number | null` – After an RPC error, how much to scale back the number of blocks requested at once
- `acceleration_additive`: `integer | null` – Without RPC errors or timeouts, how much to increase the number of blocks requested by for the next batch
- `interval_ceiling`: `integer | null` – Do not further increase the block interval past this limit
- `backoff_millis`: `integer | null` – After an error, how long to wait before retrying
- `fallback_stall_timeout`: `integer | null` – If a fallback RPC is provided, the amount of time in ms to wait before kicking off the next provider
- `query_timeout_millis`: `integer | null` – How long to wait before cancelling an RPC request

Example (config.yaml):

```yaml
chains:
  - id: 1
    rpc:
      - url: https://eth.llamarpc.com
        for: sync
      - url: wss://eth.llamarpc.com
        for: realtime
      - url: https://fallback.example.com
        for: fallback
```

### For {#def-for}

- **type**: `oneOf(const sync | const realtime | const fallback)`

Variants:
- `1`: `const sync`
- `2`: `const realtime`
- `3`: `const fallback`

### HypersyncConfig {#def-hypersyncconfig}

- **type**: `object`
- **required**: `url`

Properties:
- `url`: `string` – URL of the HyperSync endpoint (default: The most performant HyperSync endpoint for the chain)

Example (config.yaml):

```yaml
chains:
  - id: 1
    hypersync_config:
      url: https://eth.hypersync.xyz
```

### NetworkContract_for_ContractConfig {#def-networkcontractforcontractconfig}

- **type**: `object`
- **required**: `name`

Properties:
- `name`: `string` – A unique project-wide name for this contract if events and handler are defined OR a reference to the name of contract defined globally at the top level
- `address`: `object<Addresses>` – A single address or a list of addresses to be indexed. This can be left as null in the case where this contracts addresses will be registered dynamically.
- `start_block`: `integer | null` – The block at which the indexer should start ingesting data for this specific contract. If not specified, uses the chain `start_block`. Can be greater than the chain `start_block` for more specific indexing.
- `abi_file_path`: `string | null` – Relative path (from config) to a json abi. If this is used then each configured event should simply be referenced by its name
- `handler`: `string | null` – Optional explicit path to a handler file. If omitted, handlers are auto-discovered from `src/handlers/`.
- `events`: `array<object<EventConfig>>` – A list of events that should be indexed on this contract

Example (config.yaml):

```yaml
chains:
  - id: 1
    start_block: 0
    contracts:
      - name: Greeter
        address:
          - "0x1111111111111111111111111111111111111111"
        events:
          - event: Transfer(address indexed from, address indexed to, uint256 value)
```

### Addresses {#def-addresses}

- **type**: `anyOf(anyOf(string | integer) | array<anyOf(string | integer)>)`

Variants:
- `1`: `anyOf(string | integer)`
- `2`: `array<anyOf(string | integer)>`

Example (config.yaml):

```yaml
chains:
  - id: 1
    contracts:
      - name: Greeter
        address:
          - "0x1111111111111111111111111111111111111111"
          - "0x2222222222222222222222222222222222222222"
```

### AddressFormat {#def-addressformat}

- **type**: `enum (2 values)`
- **allowed**: `checksum`, `lowercase`

### Chain {#def-chain}

- **type**: `object`
- **required**: `id`, `start_block`, `contracts`

Properties:
- `id`: `integer` – The public blockchain chain ID.
- `rpc`: `anyOf(string | object<Rpc> | array<object<Rpc>> | null)` – RPC configuration for your indexer. Accepts a single URL, a single Rpc object, or an array of Rpc objects. For chains supported by HyperSync, RPC serves as a fallback for added reliability. For others, it acts as the primary data-source. WebSocket URLs (`wss://...`) are also supported for realtime endpoints.
- `hypersync_config`: `anyOf(object<HypersyncConfig> | null)` – Optional HyperSync Config for additional fine-tuning
- `start_block`: `integer` – The block at which the indexer should start ingesting data
- `end_block`: `integer | null` – The block at which the indexer should terminate.
- `contracts`: `array<object<NetworkContract_for_ContractConfig>>` – All the contracts that should be indexed on the given chain
- `max_reorg_depth`: `integer | null` – The number of blocks from the head that the indexer should account for in case of reorgs. Replaces the V2 `confirmed_block_threshold` field.
- `block_lag`: `integer | null` – Number of blocks the indexer stays behind the chain head. Replaces the V2 `ENVIO_INDEXING_BLOCK_LAG` environment variable, applied per chain.

Example (config.yaml):

```yaml
chains:
  - id: 1
    start_block: 0
    end_block: 19000000
    contracts:
      - name: Greeter
        address: "0x1111111111111111111111111111111111111111"
```

### Storage {#def-storage}

- **type**: `object`

Properties:
- `postgres`: `boolean | null` – Enable Postgres storage (default: true)
- `clickhouse`: `boolean | null` – Enable ClickHouse storage in addition to Postgres (default: false). Requires the `ENVIO_CLICKHOUSE_*` environment variables.

Example (config.yaml):

```yaml
storage:
  postgres: true
  clickhouse: true
```

## Removed in V3

The following V2 options have been removed and are no longer accepted in `config.yaml`:

- `output` — generated types are always emitted to `.envio/`.
- `unordered_multichain_mode` — unordered is now the only mode. The V2 `multichain: ordered` opt-in has also been removed.
- `event_decoder` — the Rust-based decoder is the only implementation.
- `loaders` — Preload Optimization is now always on.
- `preload_handlers` — now always enabled.
- `preRegisterDynamicContracts` — no longer needed.
- `rpc_config` — replaced by `rpc` (see above).
- `networks` — renamed to `chains`.
- `confirmed_block_threshold` — renamed to `max_reorg_depth`.

