For the complete documentation index, see llms.txt. This page is also available as Markdown.

Node.js backend

How to use the SDK in a Node.js server environment with worker threads and per-request isolation.

The SDK works in Node.js with the same API as in the browser. The main differences are the relayer (native worker threads instead of Web Workers) and storage isolation for concurrent requests.

The auth / RELAYER_API_KEY shown below is for the Zama-hosted mainnet relayer. The Sepolia testnet relayer needs no key — omit auth on testnet.

Steps

1. Install packages

npm install @zama-fhe/sdk viem

2. Create the config with a node() relayer

The node() relayer uses native worker_threads for FHE operations. Pass poolSize to control parallelism (default: min(CPU cores, 4)). Bound stuck operations with operationTimeout (seconds, default 30) — a timeout rejects with a retryable WorkerTimeoutError and recycles the worker (toggle via recycleWorkerOnTimeout).

import { createConfig } from "@zama-fhe/sdk/viem";
import { ZamaSDK, memoryStorage } from "@zama-fhe/sdk";
import { node } from "@zama-fhe/sdk/node";
import { sepolia, type FheChain } from "@zama-fhe/sdk/chains";
import { createPublicClient, createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { sepolia as sepoliaViem } from "viem/chains";

const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const publicClient = createPublicClient({ chain: sepoliaViem, transport: http() });
const walletClient = createWalletClient({ account, chain: sepoliaViem, transport: http() });

const mySepolia = {
  ...sepolia,
  network: "https://sepolia.infura.io/v3/YOUR_KEY",
  auth: { __type: "ApiKeyHeader" as const, value: process.env.RELAYER_API_KEY! },
} as const satisfies FheChain;

const config = createConfig({
  chains: [mySepolia],
  publicClient,
  walletClient,
  storage: memoryStorage,
  relayers: { [mySepolia.id]: node({ poolSize: 4 }) },
});

const sdk = new ZamaSDK(config);

3. Choose a storage backend

For scripts and single-user CLIs, memoryStorage is the simplest option (shown above).

For servers handling multiple users concurrently, use asyncLocalStorage instead — see the next step.

4. Isolate per-request state with asyncLocalStorage

On a server where each HTTP request belongs to a different user, you need per-request transport key pair isolation. asyncLocalStorage wraps Node.js AsyncLocalStorage to scope storage to the current async context.

Each call to asyncLocalStorage.run() creates a fresh storage scope. Concurrent requests never share transport key pair state.

5. Create tokens and operate

The token API is identical to the browser SDK:

See the Token Operations reference for the full API.

6. Use direct API key auth

In a server environment, you can authenticate with the relayer directly — there is no browser to leak the key to. Pass auth on the chain definition:

The auth field supports three modes. For the Zama-hosted relayer, use ApiKeyHeader — it's the only mode the hosted endpoint accepts. BearerToken and ApiKeyCookie are for self-hosted relayers or proxied setups where you control the auth layer (see the Authentication guide).

Mode
Shape
Use it when

API key header

{ __type: "ApiKeyHeader", value: "your-key" }

Zama-hosted relayer (required), or default

API key cookie

{ __type: "ApiKeyCookie", value: "your-key" }

Behind your own proxy (SDK→proxy hop)

Bearer token

{ __type: "BearerToken", token: "your-token" }

Self-hosted relayer with a bearer auth layer

7. Clean up on shutdown

Terminate the worker pool when your process exits:

8. (Optional) Use a custom signer

If you are using a transaction relayer (e.g. OpenZeppelin Defender) instead of a local wallet, implement the GenericSigner and GenericProvider interfaces and use the generic createConfig from @zama-fhe/sdk:

The signer handles signTypedData and writeContract; the provider handles readContract, waitForTransactionReceipt, getChainId, and getBlockTimestamp. See GenericSigner for the full interface.

Next steps

Last updated