Bundle an app that uses AskDB
Integrator guide
AskDB bundles into a Node service like most libraries, with one exception: from inside a bundle, @askdb/config can’t load a TypeScript askdb.config.ts. Write the config in JavaScript, keep @askdb/config out of the bundle, or use no config file. This guide covers esbuild and webpack 5.
Before you start
Section titled “Before you start”- A Node service that calls
createAskDb()orask(). Embed in a Node app sets one up. - esbuild, or webpack 5, building for Node.
1. Choose where the settings come from
Section titled “1. Choose where the settings come from”@askdb/config loads askdb.config.* from disk when your service starts. It loads a JavaScript config (.js, .cjs or .mjs) with Node’s own loader, which works from inside a bundle. A TypeScript config needs jiti, which @askdb/config uses to compile it, and jiti can’t run from inside a bundle. Three setups work:
- A JavaScript config,
createAskDb(): bundle@askdb/configwith the rest of your service, and deployaskdb.config.mjs(or.js,.cjs) next to the bundle. Nothing is installed beside the bundle, so the file can’t import anything,@askdb/configincluded: write a plainexport default { … }and read each variable fromprocess.env. This needs@askdb/config1.0.0-beta.20 or later. - A TypeScript config,
createAskDb(): leave@askdb/configout of the bundle and install it next to the bundle when you deploy.askdb.config.tsthen loads as it does without a bundler. - No config,
ask(): build the model with the AI SDK in your own code, and load the schema from one JSON file. The bundle then needs nothing installed beside it.
A JavaScript config for a bundled service looks like this. @askdb/config loads .env before the file, so process.env holds what .env sets:
export default { ai: { provider: "openai", providerConfig: { openai: { apiKey: process.env.OPENAI_API_KEY } }, language: { model: "gpt-4o-mini" }, }, introspection: { provider: "postgres", providerConfig: { postgres: { databaseUrl: process.env.DATABASE_URL } } },};Bring your own model helps you choose between them.
2. Install the provider SDK you use
Section titled “2. Install the provider SDK you use”Install ai and the AI SDK package of your provider, such as @ai-sdk/openai:
npm install ai @ai-sdk/openaipnpm add ai @ai-sdk/openaiyarn add ai @ai-sdk/openai@askdb/ai loads each provider’s SDK only when it first builds a model. esbuild leaves out the SDKs you don’t install; webpack 5 needs them listed in externals, as step 3 shows. The Vercel AI Gateway needs none. See Provider SDKs.
3. Bundle
Section titled “3. Bundle”With a TypeScript config, mark @askdb/config external. With a JavaScript config or none, drop --external:@askdb/config.
# CommonJS output. --external:@askdb/config is for a TypeScript config only.esbuild src/server.mjs --bundle --platform=node --format=cjs \ --external:@askdb/config --outfile=dist/server.cjsESM output also needs a banner that defines require. The AI SDK’s @vercel/oidc calls require("path"), and without the banner the bundle stops at startup with Dynamic require of "path" is not supported:
# ESM output. --external:@askdb/config is for a TypeScript config only.esbuild src/server.mjs --bundle --platform=node --format=esm \ --external:@askdb/config --outfile=dist/server.mjs \ --banner:js="import { createRequire as topLevelCreateRequire } from 'node:module'; const require = topLevelCreateRequire(import.meta.url);"esbuild needs nothing for the provider SDKs you didn’t install: the build succeeds, and a provider whose SDK is missing fails only when it first builds a model.
List in externals @askdb/config, with a TypeScript config, and each @ai-sdk/* package you didn’t install:
// webpack.config.cjs: CommonJS outputmodule.exports = { mode: "production", target: "node", entry: "./src/server.mjs", output: { filename: "server.cjs", library: { type: "commonjs2" } }, externals: { "@askdb/config": "commonjs @askdb/config", // with a TypeScript config only "@ai-sdk/anthropic": "commonjs @ai-sdk/anthropic", // the SDKs you don't install "@ai-sdk/azure": "commonjs @ai-sdk/azure", "@ai-sdk/google": "commonjs @ai-sdk/google", },};For ESM output, use externalsType: "module" and the bare package names. Drop "@askdb/config" from the list with a JavaScript config or none:
// webpack.config.cjs: ESM outputmodule.exports = { mode: "production", target: "node", entry: "./src/server.mjs", experiments: { outputModule: true }, output: { filename: "server.mjs", module: true, library: { type: "module" }, chunkFormat: "module" }, externalsType: "module", externals: ["@askdb/config", "@ai-sdk/anthropic", "@ai-sdk/azure", "@ai-sdk/google"],};Without the SDK entries, webpack stops with Module not found: Error: Can't resolve '@ai-sdk/anthropic' for each SDK you didn’t install. An app that imports only @askdb/core needs none of them, because @askdb/ai is what loads the SDKs.
4. Ship the schema as one file
Section titled “4. Ship the schema as one file”The schema artifact is a directory that your service reads at run time, so the bundler doesn’t include it. Turn it into one JSON file with askdb bundle, and ship that file next to the bundle:
npx askdb bundle ./my-app.schema --out ./my-app.schema.bundle.jsonLoad it like a schema directory. With a config file, pass it to createAskDb(), or set host.schemaPath to it:
const askdb = createAskDb({ config: getAskDbRuntimeConfig(), schema: { path: "./my-app.schema.bundle.json" },});Without one, load it with loadSchema() and pass your model to ask():
import { ask, loadSchema } from "@askdb/core";import { openai } from "@ai-sdk/openai";
const schema = loadSchema("./my-app.schema.bundle.json");const model = openai("gpt-4o-mini"); // reads OPENAI_API_KEY from the environment
const { sql } = await ask({ question, schema, dialect: "postgres", model });5. Deploy
Section titled “5. Deploy”With a JavaScript config, deploy the bundle, askdb.config.mjs, the schema file and your .env or environment variables. Nothing else needs installing. Start the service from that directory, where bootstrapAskDbEnv({ cwd: process.cwd() }) looks for the config.
With a TypeScript config, deploy the bundle, askdb.config.ts, the schema file and your .env or environment variables, and install @askdb/config in that directory:
npm install @askdb/configpnpm add @askdb/configyarn add @askdb/configIt brings jiti and dotenv, which load the config. Start the service from that directory.
Without one, deploy the bundle and the schema file, and set your provider’s key in the environment. Nothing else needs installing.
If it fails
Section titled “If it fails”| Error | Fix |
|---|---|
createRequire is not a function (webpack); The argument 'filename' must be a file URL object, file URL string, or absolute path string. Received undefined or Cannot find module '../dist/babel.cjs' (esbuild) | A TypeScript config, with @askdb/config inside the bundle. Mark it external and install it next to the bundle, or write the config in JavaScript. On @askdb/config older than 1.0.0-beta.20, a JavaScript config fails this way too. |
Cannot find module '@askdb/config', or Cannot find package '@askdb/config' | @askdb/config is external but not installed where the bundle runs: install it there. Or your JavaScript config imports it: remove the import, and read variables from process.env. |
SyntaxError: Unexpected token 'export', or Cannot use import statement outside a module | Node reads your askdb.config.js as CommonJS. Rename it to askdb.config.mjs, or write it with module.exports = { … }. |
Module not found: Error: Can't resolve '@ai-sdk/<name>' (webpack) | Install that SDK, or add it to externals. |
Provider '<name>' requires the optional peer dependency @ai-sdk/<name> | The SDK of the provider your config selects isn’t in the bundle. Install it and bundle again. |
Dynamic require of "path" is not supported (esbuild ESM) | Add the createRequire banner from step 3. |
Read next
Section titled “Read next”© 2026 Yahya Gilany

