> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://docs.ampdb.io/api/mcp` to find what you need.

# Static Datasets

Status: In development.

A static dataset makes CSV files queryable as SQL tables: reference data like labels for addresses or blocks, token
lists, or prices you computed elsewhere. You can join it with chain data in your queries.

Its data isn't tied to blocks, and Amp doesn't extract it: the files stay where you put them, in a local directory or
a bucket, and Amp reads them each time you query. There's nothing to deploy. A static dataset is queryable as soon as
it's registered.

## Prerequisites

* A running Amp you can manage, like one in [solo mode](/running-amp/solo-mode).
* [`ampctl`](/clis/ampctl) and [`ampsql`](/clis/ampsql), which install with Amp.
* Somewhere for the CSV files that the `ampd` processes answering queries can read: a local directory, or an Amazon
  S3, Google Cloud Storage, or Azure Blob Storage bucket, with its credentials in `ampd`'s environment (see
  [Static](/providers/static#credentials)).

## How Amp finds the files

A static dataset's manifest gives each table's file as a relative `path`, like `labels/block_labels.csv`. The path
never names a bucket or a host. Its first segment, `labels`, is a routing token: it picks the
[static provider](/providers/static) whose `object_store_root` ends in the same segment. Amp reads the file at that
root, followed by the rest of the path:

| Table `path`              | Provider's `object_store_root` | File Amp reads                               |
| ------------------------- | ------------------------------ | -------------------------------------------- |
| `labels/block_labels.csv` | `file:///srv/amp/labels`       | `file:///srv/amp/labels/block_labels.csv`    |
| `labels/block_labels.csv` | `s3://prod-bucket/labels/`     | `s3://prod-bucket/labels/block_labels.csv`   |
| `labels/2026/prices.csv`  | `gs://reference-data/labels`   | `gs://reference-data/labels/2026/prices.csv` |

So the same dataset reads local files in development and a bucket in production: you register a different provider,
and the dataset doesn't change. Name tokens after what the files are, like `labels` or `prices`, rather than where they
are. Tokens are case-sensitive.

## Create a static dataset

::::steps
### Put the CSV file in place

Put the file in a directory whose last segment is the routing token, here `labels`:

```csv [/srv/amp/labels/block_labels.csv]
block_num,name,description
24000000,first,The dataset's first block
24000072,busy,A block that used almost all of its gas
24000099,last,The dataset's last block
```

### Register a static provider

The provider points to the directory. Its name doesn't matter to the dataset; its root's last segment does.

```toml [labels.toml]
kind = "static"
object_store_root = "file:///srv/amp/labels"
```

```bash
ampctl provider register labels ./labels.toml
```

### Write the manifest

Declare each table's file, its format, and its columns. Amp doesn't infer columns from the file: list them, in the
file's order, with their [types](/datasets/manifests#data-types).

```json [block_labels.json]
{
  "kind": "static",
  "tables": {
    "block_labels": {
      "path": "labels/block_labels.csv",
      "format": "csv",
      "has_header": true,
      "schema": {
        "arrow": {
          "fields": [
            { "name": "block_num", "type": "UInt64", "nullable": false },
            { "name": "name", "type": "Utf8", "nullable": false },
            { "name": "description", "type": "Utf8", "nullable": false }
          ]
        }
      }
    }
  }
}
```

### Register the dataset

```bash
ampctl dataset register acme/block_labels ./block_labels.json --tag 1.0.0
```

### Query it

:::terminal
```bash
ampsql 'SELECT * FROM "acme/block_labels".block_labels ORDER BY block_num'
```

```
+-----------+-------+-----------------------------------------+
| block_num | name  | description                             |
+-----------+-------+-----------------------------------------+
| 24000000  | first | The dataset's first block               |
| 24000072  | busy  | A block that used almost all of its gas |
| 24000099  | last  | The dataset's last block                |
+-----------+-------+-----------------------------------------+
```
:::

Join it with other datasets like any table. With the Ethereum mainnet dataset that the
[Quickstart](/get-started/quickstart) deploys:

:::terminal
```bash
ampsql 'SELECT b.block_num, b.gas_used, l.name FROM "acme/eth_mainnet".blocks b JOIN "acme/block_labels".block_labels l ON b.block_num = l.block_num ORDER BY b.block_num'
```

```
+-----------+----------+-------+
| block_num | gas_used | name  |
+-----------+----------+-------+
| 24000000  | 57860235 | first |
| 24000072  | 59998750 | busy  |
| 24000099  | 10751338 | last  |
+-----------+----------+-------+
```
:::
::::

## The manifest

A static manifest has a `kind` of `static` and its `tables`. Each table has:

* `path`: the file, as `<routing token>/<path in the provider's storage>`. It's relative, uses `/`, has at least two
  segments, ends in a file name with an extension, and never contains `..`.
* `format`: `csv`, the only format supported.
* `has_header`: whether the file's first line names the columns, which Amp then skips.
* `schema`: the columns, in the file's order.
* `sorted_by`, optional: the columns the file is already sorted by, which saves queries a sort.

Every field is in the [Manifest Reference](/datasets/manifest-reference#static-datasets).

## Limitations

* CSV files only.
* Read-only, in one-shot queries: you can't deploy a static dataset, read it from a
  [derived dataset](/datasets/derived-datasets), or stream it. Join it when you query instead.
* Amp reads a file each time you query it, so changes to the file show in the next query. Nothing tells clients that
  the data changed.
* When two static providers have the same routing token, Amp uses the one whose name comes first alphabetically, and
  logs a warning.

## Errors

### ``no `static` provider matches routing token``

A query fails with ``Error during planning: no `static` provider matches routing token `prices` `` when no static
provider's `object_store_root` ends in the table path's first segment. Register one, or fix the path's first segment.
Check the case: `Labels` and `labels` are different tokens.

### `data file path must contain at least one segment after the routing token`

Registration fails with `INVALID_MANIFEST` when a table's `path` has a single segment, like `block_labels.csv`. Start
it with a routing token: `labels/block_labels.csv`.

### `STATIC_DATASET_NOT_MATERIALIZABLE`

`ampctl dataset deploy` fails with `static datasets cannot be materialized`. Static datasets need no deployment: query
them as soon as they're registered.

### File or credential errors

A file that's missing, unreadable, or in a bucket `ampd` has no credentials for fails the first query that reads it,
not registration. Check the path, and the credentials in `ampd`'s environment.
