Migrate to HyperIndex V3
This guide is a plain, step-by-step checklist of every change required to upgrade an existing HyperIndex V2 project to V3. For an overview of new V3 capabilities, see What's New in V3.
Follow the steps in order. Each step is independent enough to skim, but Step 0 (preparation on V2) is strongly recommended before you start touching V3 code.
Step 0: Prepare on V2 (Recommended)
Before upgrading to V3, prepare your project while still on V2:
-
Upgrade to
envio@2.32.6. -
Enable Preload Optimization in
config.yaml:preload_handlers: true -
If you were using loaders, migrate them to Preload Optimization following the Migrating from Loaders guide.
-
Verify your indexer still works with
pnpm dev.
Step 1: Update Node.js
Update Node.js to 22 or higher (24 is recommended). Earlier versions are no longer supported.
Step 2: Update package.json
-
Add
"type": "module"(required — without it the project will fail to start with ESM import errors). -
Set
engines.nodeto>=22.0.0. -
Update the
enviodependency to the latest v3 release. -
Remove the
optionalDependencies.generatedentry — the localgeneratedpackage no longer exists. Types are emitted to.envio/types.d.ts(git-ignored) and wired up via a smallenvio-env.d.tsfile at the project root. Everything previously imported fromgeneratedis now exported fromenvio.- "optionalDependencies": {
- "generated": "./generated"
- }, -
Update dev tooling:
{
"type": "module",
"engines": {
"node": ">=22.0.0"
},
"dependencies": {
"envio": "3.0.0-rc.0"
},
"devDependencies": {
"@types/node": "24.12.2",
"typescript": "6.0.3",
"vitest": "4.1.0"
}
} -
If you used
ts-nodefor the start script, replace it withenvio start:{
"scripts": {
"start": "envio start"
}
}
Test runner
Option A — Migrate to Vitest (recommended).
pnpm remove ts-mocha ts-node mocha chai @types/mocha @types/chai
pnpm add -D vitest@4.0.16
{
"scripts": {
"test": "vitest run"
},
"devDependencies": {
"vitest": "4.0.16"
}
}
Move tests from test/Test.ts to src/indexer.test.ts and update imports:
// Before (mocha/chai)
import { describe, it } from "mocha";
import { expect } from "chai";
// After (vitest)
import { describe, it, expect } from "vitest";
import { createTestIndexer } from "envio";
Option B — Keep Mocha. Replace ts-mocha/ts-node with tsx:
pnpm remove ts-mocha ts-node
pnpm add -D tsx@4.21.0
{
"scripts": {
"mocha": "tsc --noEmit && NODE_OPTIONS='--no-warnings --import tsx' mocha --exit test/**/*.ts"
}
}
Step 3: Update tsconfig.json
Update for ESM:
{
/* For details: https://www.totaltypescript.com/tsconfig-cheat-sheet */
"compilerOptions": {
/* Base Options: */
"esModuleInterop": true,
"skipLibCheck": true,
"target": "es2022",
"allowJs": true,
"resolveJsonModule": true,
"moduleDetection": "force",
"isolatedModules": true,
"verbatimModuleSyntax": true,
/* Strictness */
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
/* For running Envio: */
"module": "ESNext",
"moduleResolution": "bundler",
"noEmit": true,
/* Code doesn't run in the DOM: */
"lib": ["es2022"],
"types": ["node"]
}
}
verbatimModuleSyntax and noUncheckedIndexedAccess are extra strictness. You can disable them to simplify the migration.
Step 4: Update config.yaml
Renames
networks→chainsconfirmed_block_threshold→max_reorg_depthrpc_config→rpc(now supports multiple URLs,for: sync | realtime | fallback, and WebSocket configuration)
# Before
networks:
- id: 1
contracts:
- name: MyContract
events:
- event: Transfer(address indexed from, address indexed to, uint256 value)
# After
chains:
- id: 1
contracts:
- name: MyContract
events:
- event: Transfer(address indexed from, address indexed to, uint256 value)
Removals
Remove these options if present:
unordered_multichain_mode— unordered is now the only mode in V3. The V2multichain: orderedopt-in has also been removed.loaders— Preload Optimization is now always enabled.preload_handlers— now always enabled.preRegisterDynamicContracts— no longer needed.event_decoder— the Rust-based decoder is now the only implementation.output— generated types are always emitted to.envio/.
Replacements for environment variables
If you were using the MAX_BATCH_SIZE environment variable, switch to the config option:
full_batch_size: 5000
Optional: Automatic handler registration
Move handler files to src/handlers/ and remove the explicit handler paths from config.yaml. The explicit handler field still works if you'd rather not move files immediately.
Optional: ClickHouse storage
If using ClickHouse, add:
storage:
postgres: true
clickhouse: true
The connection environment variables (ENVIO_CLICKHOUSE_HOST, ENVIO_CLICKHOUSE_DATABASE, ENVIO_CLICKHOUSE_USERNAME, ENVIO_CLICKHOUSE_PASSWORD) are still required for envio start.