Skip to content

KDB-X Modules

This page guides you through creating and using KDB-X modules in kdb Insights Enterprise, from declaring dependencies to hot-reloading in running processes. If you're new to KDB-X modules in kdb Insights Enterprise, start with the KDB-X modules overview.

KDB-X modules are a unit of encapsulation in KDB-X. They have access to their own local namespace that can contain internal and external functions and variables for the module, as opposed to designating a fixed global namespace as it is often done for pre-module libraries.

Modules expose variables and functions using the export variable, which code can then import with the use function and assign to an arbitrary name. You can write modules in q or with the C API.

Declaring dependencies

Packages declare their dependencies in the dependencies section of the package's manifest.yaml. Each service container has a sidecar helper that resolves and downloads them before startup, making them available to use in q or import in Python.

Example manifest.yaml:

# manifest.yaml
name: my-app
version: 1.0.0
dependencies:
  - myutils>=1.0.0
  - modb==2.0.0

Pulling KDB-X modules from the Downloads Portal

KX owned modules are available through the KX Downloads Portal. To allow the Package Manager service to pull from that portal, set your bearer token as follows:

kxi pm config set DOWNLOADS_PORTAL_TOKEN <your-token>

Once configured, any package that lists a KX module in its dependencies has it resolved automatically on deploy.

Permissions

You need the Administrator role to run kxi pm config set. Refer to Roles for details.

Creating a module

In this section, you will create the myutils example module from scratch. A completed reference copy is available here: myutils.zip.

The myutils module is a runnable q module — refer to the KDB-X module quickstart for details on its structure. In kdb Insights Enterprise a manifest.yaml is required to declare the module's name and version.

manifest.yaml

Create this file at the top level of your module directory:

name: myutils
version: 1.0.0

init.q

Define the module's public API by assigning export to a dictionary (or keyed table) of the values you want to expose:

.myutils.greet:{[name] raze "Hello, ",name}
.myutils.PI:3.14159

export:([greet:.myutils.greet; PI:.myutils.PI])

Push the module to the Package Manager:

kxi pm push myutils

Once pushed, any package can declare the module as a dependency.

Using a module in another package

In this section, you will use the myutils module you created as a dependency in a new package. A completed reference copy of the full example package is available here: kdbx-mod-eg.zip. This contains additional configuration files (tables, databases, pipelines, router) required to run the full example.

1. Declare the dependency in the package's manifest.yaml

Add the module name to the dependencies list of your package. A version specifier is optional but recommended:

name: kdbx-mod-eg
version: 1.0.9
dependencies:
  - myutils>=1.0.0

Supported specifiers: ==, >=, <=, >, <, ~=. Without a specifier the latest available version is used.

2. Load the module with use

In any .q file within the package, import the module and access exported functions/variables:

.utils: use `myutils;

// call an exported function
.utils.greet "world"

// read an exported value
show .utils.PI

3. Use a module inside a code pipeline

.utils: use `myutils;
pub: {send ``name!2?`3};
.qsp.onStart {.tm.add[`sendStuff;(`pub;::);1000;0]};
.qsp.onTeardown {.tm.del`sendStuff};
.qsp.run
    .qsp.read.fromCallback[`send]
    .qsp.map[{[msg] raze .utils.greet string msg`name}]
    .qsp.write.toConsole[.qsp.use ``qlog!(::;1b)]

After executing the pipeline the logs will show the following:

 kxi obs logs --workload=kdbx-mod-eg | tail -5
{"component":"console","container":"spwork","level":"INFO","message":"\"Hello, ehn\"","pod":"kdbx-mod-eg-pipeline-1-spwork-0","time":"2026-04-22T11:13:25.923z"}
{"component":"console","container":"spwork","level":"INFO","message":"\"Hello, oba\"","pod":"kdbx-mod-eg-pipeline-1-spwork-0","time":"2026-04-22T11:13:26.921z"}
{"component":"console","container":"spwork","level":"INFO","message":"\"Hello, bna\"","pod":"kdbx-mod-eg-pipeline-1-spwork-0","time":"2026-04-22T11:13:27.922z"}
{"component":"console","container":"spwork","level":"INFO","message":"\"Hello, ljm\"","pod":"kdbx-mod-eg-pipeline-1-spwork-0","time":"2026-04-22T11:13:28.922z"}
{"component":"console","container":"spwork","level":"INFO","message":"\"Hello, glj\"","pod":"kdbx-mod-eg-pipeline-1-spwork-0","time":"2026-04-22T11:13:29.923z"}

4. Use a module inside a UDA

Load the module with use in the UDA query function that runs on each DAP:

src/da.q

.utils: use `myutils;

.myuda.query:{[table;startTS;endTS]
    res:.kxi.selectTable`table`startTS`endTS!(table;startTS;endTS);
    res:update label:.utils.greet each string sym from res;
    .kxi.response.ok res
    };

metadata:.kxi.metaDescription["Greet each sym in the trades table."],
    .kxi.metaParam[`name`type`isReq`description!(`table;-11h;1b;"Table name.")],
    .kxi.metaParam[`name`type`isReq`description!(`startTS;-12h;1b;"Start time.")],
    .kxi.metaParam[`name`type`isReq`description`default!(`endTS;-12h;0b;"End time.";.z.P)];

.kxi.registerUDA`name`query`metadata!(`.myuda;`.myuda.query;metadata);

The package manifest.yaml declares the dependency on myutils and loads the entry point:

name: kdbx-mod-eg
version: 1.0.9
dependencies:
  - myutils>=1.0.0
entrypoints:
  data-access: src/da.q
pipelines:
  pipeline:
    file: pipelines/pipeline.yaml
tables:
  trades:
    file: tables/trades.yaml
databases:
  kdbx-mod-eg:
    dir: databases/kdbx-mod-eg
    shards:
      - kdbx-mod-eg
    tables: []

Chaining module dependencies

Modules can also declare dependencies on other modules in their own manifest.yaml, under dependencies. When you deploy a package that depends on the module, the Package Manager resolves and downloads all modules in the dependency graph together.

kxi pm push modc/
kxi pm push modb/   # depends on modc
kxi pm push moda/   # depends on modb

Any consumer that declares moda as a dependency gets modb and modc resolved transitively.

Version conflicts

If two packages in the same deployment declare different versions of the same module, the Package Manager fails at deploy time with a conflict error and the container will not become ready. To avoid conflicts, align module versions across packages or use a compatible version specifier such as >= or ~=.

Hot-reloading modules in DAPs and Aggs

Use kxi pm load to push a new package version into running processes without a full restart:

kxi pm load myutils --version 1.1.0 --deployment kdbx-mod-eg --targets daps,pkg_agg --global-processes agg

For this to work correctly, modules loaded into DAPs, Aggregators, or the Global Aggregator must use .Q.m.reuse instead of plain use. .Q.m.reuse loads the module on first call and reloads it on subsequent calls, so a hot-reload picks up the new version:

.utils: .Q.m.reuse `myutils;

Using plain use in a DAP or Aggregator causes the first-loaded version to remain cached after a kxi pm load.Q.m.reuse is required for the reload to take effect.

Warning

kxi pm load only updates the running process. It does not update the package's saved dependencies, so the change will not survive a restart or redeployment. To make the update permanent, bump the version in the package's manifest.yaml and redeploy.

Global Aggregator

The Package Manager does not manage the Global Aggregator, so there is no first-class solution for persisting a hot-reload. The only option is to update KX_PACKAGES to the space-delimited set of packages and modules you want downloaded on startup. Refer to Loading UDAs into Global Aggregators for details on how to do this, including how to persist changes across upgrades.

Loading modules in a Scratchpad

Permissions

You need the Administrator role to run .kxi.install. Refer to Roles for details.

Install a module by calling .kxi.install with the package name:

.kxi.install["myutils"]

Supported version specifiers are ==, >=, <=, >, <, and ~=. Without a specifier the latest available version is used:

.kxi.install["myutils==1.0.0"]

Once installed, import the module using use:

.utils: use `myutils;
.utils.greet "world"

Comparison with .kxi.packages.load

.kxi.packages.load still works for non-module packages, but the recommended approach is to declare dependencies in the dependencies section of the package's manifest.yaml – refer to Package Dependency for the dependency format.

.kxi.packages.load .kxi.install + use
Installs package Yes Yes
Runs package init script Yes No
Makes module importable with use No Yes
Suitable for KDB-X modules No Yes
Suitable for non-module packages Yes Yes, but not importable with use

Troubleshooting

Issue Likely cause Resolution
Module not found at startup KX_PACKAGES not set or package not published Verify with kxi pm list
Hot-reload not taking effect Module loaded with use instead of .Q.m.reuse Replace use with .Q.m.reuse
Modules lost after restart Loaded via kxi pm load only KX_PACKAGES must be set persistently – refer to your platform administrator
.kxi.install not found Running on IE < 1.19 Upgrade to 1.19 or later
use fails after install Incorrect module path or KX_PACKAGE_PATH not set Check the module hierarchy in the package and verify KX_PACKAGE_PATH is configured
Version not available Requested version not published Check available versions with kxi pm info <package>
Back to top