---
title: "@thru/indexer"
description: Reusable indexing framework for Thru chain streams, schemas,
  checkpoints, and Drizzle-backed runtimes.
source_url:
  html: https://thru.org/docs/sdks/web-packages/indexer/
  md: https://thru.org/docs/sdks/web-packages/indexer.md
---

# @thru/indexer

`@thru/indexer` is the public root entrypoint for building persistent Thru indexers. The package exposes a single published entrypoint at the package root; there are no public subpath exports.

## Install

```bash
npm install @thru/indexer @thru/replay @thru/sdk postgres drizzle-orm
```

You will also need a database driver and a Drizzle database/schema setup in the application that runs the indexer.

## When To Use It

Use `@thru/indexer` when you want to:

- define event streams for historical chain data
- define account streams for mutable on-chain state
- build Drizzle tables from stream definitions
- persist checkpoints so an indexer can resume after a restart
- run a background indexer that processes event and account streams together

Choose a different package when:

- you only need an ordered feed and do not want to store results yourself: use [`@thru/replay`](https://thru.org/docs/sdks/web-packages/replay.md)
- you only need direct chain reads or writes: use [`@thru/sdk`](https://thru.org/docs/sdks/web-packages/sdk.md)
- you only need low-level encoding helpers: use `@thru/sdk/helpers`

## Main Exports

| Area | Export | What it does |
| - | - | - |
| Schema builder | `t`, `columnBuilder` | Define typed columns for stream-backed Drizzle tables. |
| Validation | `generateZodSchema`, `validateParsedData` | Validate parsed rows during development or debugging. |
| Stream definitions | `defineEventStream`, `defineAccountStream` | Compile event and account stream definitions into runnable stream objects with `.table` exports. |
| Checkpoints | `checkpointTable`, `getCheckpoint`, `updateCheckpoint`, `deleteCheckpoint`, `getAllCheckpoints`, `getSchemaExports` | Store resumable progress and collect tables for migrations. |
| Runtime | `Indexer` | Run configured event and account streams against a database and replay client factory. |
| Shared types | `ApiConfig`, `StreamBatch`, `HookContext`, `IndexerConfig`, `IndexerResult` | Type stream hooks, config, and runtime results. |

## Typical Workflow

```ts
import {
  Indexer,
  checkpointTable,
  defineAccountStream,
  defineEventStream,
  t,
} from "@thru/indexer";
import { ChainClient } from "@thru/replay";

const indexer = new Indexer({
  db,
  clientFactory: () => new ChainClient({ baseUrl: process.env.CHAIN_RPC_URL! }),
  eventStreams: [transfers],
  accountStreams: [tokenAccounts],
  defaultStartSlot: 0n,
  safetyMargin: 64,
  pageSize: 512,
});

await indexer.start();
```

`defineEventStream` is for append-only chain events. `defineAccountStream` is for current account state that gets updated as chain data changes. Both return compiled stream objects with a Drizzle table on `.table`, which keeps schema and runtime definitions aligned.

`Indexer` is the runtime layer. Its config requires a database client and a `clientFactory`, and it supports event streams, account streams, a default start slot, safety margin, page size, and optional runtime validation.

## Reading Indexed Data

`@thru/indexer` writes ordinary Drizzle tables. Query them directly from your backend.

```ts
import { desc, eq } from "drizzle-orm";
import { db } from "./db";
import { tokenTransferEvents } from "./schema";

const recentTransfers = await db
  .select()
  .from(tokenTransferEvents)
  .where(eq(tokenTransferEvents.dest, "ta..."))
  .orderBy(desc(tokenTransferEvents.slot))
  .limit(20);
```

## Related Guides

- [Indexing Overview](https://thru.org/docs/indexing/overview.md) for package selection and the full indexing guide structure.
- [Build an Indexer](https://thru.org/docs/indexing/build-an-indexer.md) for a step-by-step guide with production concerns.
- [`@thru/replay`](https://thru.org/docs/sdks/web-packages/replay.md) for the replay primitives that power the indexer runtime.
- [`@thru/sdk`](https://thru.org/docs/sdks/web-packages/sdk.md) for the app-facing RPC SDK.
