Quickstart
Choose between configure() and connect().
Engine configuration
@xbbg/core engine.One EngineConfig object controls the Bloomberg transport, authorization, TLS, worker pools, request policies, subscription buffers, and logging. Every field is optional.
import { Engine, configure, connect } from '@xbbg/core';
// Defaults for the top-level helpers (bdp, blp.abdh, subscribe, ...).
// Nothing connects until the first helper call.
configure({ host: 'localhost', port: 8194, requestTimeoutMs: 120_000 });
// A dedicated engine; the session starts off the event loop.
const engine = await connect({ host: 'localhost', port: 8194 });
// The same factory as a static method.
const other = await Engine.connect({ host: 'localhost', port: 8194, requestPoolSize: 4 });
console.log(engine.isAvailable(), other.isAvailable());configure(host, port) is shorthand for configure({ host, port }). new Engine(host, port) and Engine.withConfig(config) build an engine synchronously and block the event loop until the session is up; prefer connect() in servers.
Values are validated when the engine is built, before any Bloomberg session starts. An invalid value rejects connect() (or the first helper call after configure()) with a BlpError that names the field:
import { BlpError, connect } from '@xbbg/core';
try {
await connect({ requestPoolSize: 0 });
} catch (error) {
if (error instanceof BlpError) {
console.error(error.message); // requestPoolSize must be greater than zero
}
}| Field | Default | Meaning |
|---|---|---|
host | 'localhost' | Host of a Desktop API session or a direct Bloomberg endpoint |
port | 8194 | Port for host |
servers | none | Ordered failover list of { host, port }; replaces host and port when set |
zfpRemote | none | '8194' or '8196': connect over a ZFP leased line to Bloomberg-supplied endpoints. Requires tls; cannot be combined with host, port, servers, or socks5 |
auth | none | Session identity authorization; see Authorization |
tls | none | TLS client credentials and trust material; see TLS |
socks5 | none | { host, port } of a SOCKS5 proxy, applied to every direct endpoint |
numStartAttempts | 3 | Session start attempts before the engine fails to start |
autoRestartOnDisconnection | true | Let the Bloomberg SDK restart a session after a disconnect |
import { connect } from '@xbbg/core';
const engine = await connect({
servers: [
{ host: 'bbg-primary.example.com', port: 8194 },
{ host: 'bbg-secondary.example.com', port: 8194 },
],
auth: { method: 'userapp', appName: 'my-bpipe-app' },
tls: {
clientCredentials: '/path/to/client.p12',
clientCredentialsPassword: process.env.BPIPE_TLS_PASSWORD,
trustMaterial: '/path/to/trust.p7',
},
});Servers are tried in list order. Use host and port instead for a single endpoint.
auth authorizes the session identity. The method decides which other fields are required:
method | Required fields | Identity |
|---|---|---|
'user' | none | The operating-system logon user |
'app' | appName | A registered application |
'userapp' | appName | The logon user together with an application |
'dir' or 'directory' | dirProperty | A user looked up through an Active Directory property |
'manual' | appName, userId, ipAddress | An explicitly supplied user and IP address with an application |
'token' | token | A pre-generated authorization token |
import { connect } from '@xbbg/core';
const engine = await connect({
host: 'bpipe-host',
port: 8194,
auth: { method: 'token', token: process.env.BPIPE_AUTH_TOKEN ?? '' },
});A missing required field fails validation, for example auth.appName is required for auth.method='app'. Identity operations such as engine.seatType() and engine.checkEntitlements() authorize with this configuration, or with the Desktop logon user when auth is not set.
tls.clientCredentials (PKCS#12) and tls.trustMaterial (PKCS#7) are either two file paths or two in-memory byte arrays (Buffer or Uint8Array) holding DER data. Mixing a path with bytes is rejected.
| Field | Meaning |
|---|---|
clientCredentials | File path, or DER PKCS#12 client credentials |
clientCredentialsPassword | Password for the client credentials |
trustMaterial | File path, or DER PKCS#7 trusted certificates |
handshakeTimeoutMs | TLS handshake timeout; non-negative; SDK default when omitted |
crlFetchTimeoutMs | Certificate revocation list fetch timeout; non-negative; SDK default when omitted |
Byte arrays suit credentials kept in a secret store:
import { connect } from '@xbbg/core';
// For example, base64 values injected from a secret store
const clientCredentials = Buffer.from(process.env.BPIPE_CLIENT_P12_B64 ?? '', 'base64');
const trustMaterial = Buffer.from(process.env.BPIPE_TRUST_P7_B64 ?? '', 'base64');
const engine = await connect({
host: 'bpipe-host',
port: 8194,
auth: { method: 'app', appName: 'my-bpipe-app' },
tls: {
clientCredentials,
clientCredentialsPassword: process.env.BPIPE_TLS_PASSWORD,
trustMaterial,
},
});Bytes are copied into immutable engine-owned storage before the asynchronous startup begins, so later changes to your buffers have no effect, and they are never written to temporary files. SharedArrayBuffer-backed, detached, and non-Uint8Array views are rejected.
import { connect } from '@xbbg/core';
const engine = await connect({
zfpRemote: '8194',
tls: {
clientCredentials: '/path/to/client.p12',
clientCredentialsPassword: process.env.BPIPE_TLS_PASSWORD,
trustMaterial: '/path/to/trust.p7',
},
});ZFP obtains Bloomberg's endpoints for the leased line from the SDK, so it requires tls and rejects host, port, servers, and socks5 during validation instead of silently connecting to localhost:8194.
import { connect } from '@xbbg/core';
const engine = await connect({
host: 'bpipe-host',
port: 8194,
socks5: { host: 'proxy.example.com', port: 1080 },
});The proxy applies to host/port or to every entry in servers. Both socks5.host and socks5.port are required.
| Field | Default | Meaning |
|---|---|---|
requestTimeoutMs | 0 | Hard per-request timeout in milliseconds; 0 disables it. A request that runs out of time rejects with BlpTimeoutError |
retryPolicy | { maxRetries: 0, initialDelayMs: 1000, backoffFactor: 2, maxDelayMs: 30000 } | Retries for transient failures; no retries by default |
validationMode | 'disabled' | Field validation for bdp, bds, and bdh: 'disabled', 'lenient', or 'strict' |
fieldCachePath | ~/.xbbg/field_cache.json | File for the persisted field-type cache |
bqlAppName | none | Default BQL clientContext.appName; see BQL application context |
keyColumn | 'ticker' (deprecated) | Name of the column that holds each row's security in reference, historical, bulk, intraday, BQL, and recipe results: 'ticker' or 'security'. The 'ticker' default collides with Bloomberg's TICKER field once names are case-folded; the first result that uses it emits one DeprecationWarning per process (code XBBG_TICKER_KEY_COLUMN), and 'security' becomes the default in the next major release. Subscription rows keep topic |
import { connect } from '@xbbg/core';
const engine = await connect({
requestTimeoutMs: 120_000,
retryPolicy: { maxRetries: 3, initialDelayMs: 500, backoffFactor: 2, maxDelayMs: 10_000 },
validationMode: 'strict',
keyColumn: 'security',
});initialDelayMs * backoffFactor ** (n - 1), capped at maxDelayMs.'strict' checks the requested fields, given as mnemonics or Bloomberg field ids, with //blp/apiflds first and rejects unknown ones with a BlpValidationError that includes Bloomberg's refusal details; 'lenient' logs a warning and sends the request unchanged. The per-request validateFields option on bdp, bds, and bdh overrides the engine setting: true validates strictly, false skips validation.| Field | Default | Meaning |
|---|---|---|
shardRequests | false | Split eligible multi-security bdp and bdh requests into concurrent shards |
shardThreshold | 20 | Minimum number of securities before a request is sharded (at least 2) |
shardChunkSize | 16 | Maximum securities per shard |
shardMaxConcurrent | 4 | Maximum in-flight shards per request |
Sharded results keep the input order. Requests with per-security overrides are split along contiguous override groups. Result metadata, entitlement IDs, and Bloomberg RequestIds from all shards are merged.
| Field | Default | Meaning |
|---|---|---|
requestPoolSize | 2 | Request workers, each with its own Bloomberg session (at least 1) |
runtimeWorkerThreads | 2 | Threads in the engine's async runtime (at least 1); not the process thread count |
subscriptionPoolSize | 1 | Subscription sessions started with the engine (0 or more) |
maxSubscriptionSessions | 32 | Cap on live subscription sessions (at least 1, and at least subscriptionPoolSize); new subscriptions wait for capacity instead of opening more |
warmupServices | ['//blp/refdata', '//blp/apiflds'] | Services opened when request workers start |
A subscription that only joins existing shared feeds uses no extra session.
| Field | Default | Meaning |
|---|---|---|
subscriptionStreamCapacity | 256 | Buffer size per subscription (at least 1); streamCapacity overrides it per subscription |
overflowPolicy | 'drop_newest' | When a delta subscription's buffer is full: 'drop_newest' ends it with BlpSubscriptionDataLossError; 'block' waits briefly on a bounded forwarding task, then fails the same way; 'drop_oldest' evicts the oldest pending updates, reports the exact count as a gap, and requires sub.deliveries() reads. Bloomberg's callback thread never waits |
subscriptionFlushThreshold | 16 | Maximum number of already-queued updates combined into one subscription read batch (at least 1). Reads never wait for a batch to fill, so quiet streams still get one-row batches; scalar iteration still yields one Tick per update. flushThreshold overrides it per subscription |
streamsDeactivatedWarnMs | 30000 | Add a warning event when a topic's streams stay deactivated this long; 0 disables |
maxEventQueueSize | 10000 | Bloomberg SDK event queue size |
commandQueueSize | 256 | Internal command channel capacity (at least 1) |
slowConsumerHiWaterMark | SDK default (0.75) | Slow-consumer warning threshold, as a fraction of maxEventQueueSize from 0 to 1 |
slowConsumerLoWaterMark | SDK default (0.5) | Fraction at which the slow-consumer warning clears, from 0 up to but not including 1 |
keepAliveEnabled | true | Bloomberg SDK keep-alive pings |
keepAliveInactivityMs | SDK default (20000) | Idle time before a keep-alive ping is sent |
keepAliveResponseTimeoutMs | SDK default (10000) | Wait for a keep-alive response before the connection is declared down |
import { connect } from '@xbbg/core';
// A WAN link that drops quiet connections
const engine = await connect({
host: 'bpipe-host',
port: 8194,
keepAliveInactivityMs: 60_000,
keepAliveResponseTimeoutMs: 30_000,
});With the SDK defaults, about 30 seconds of silence (20 seconds idle plus 10 seconds waiting for a response) marks a connection as down; raise both values for VPN or WAN links that see spurious disconnects.
bqlAppName is an optional default for the BQL clientContext.appName request element. It must not be blank when set.
import { configure, connect } from '@xbbg/core';
configure({ bqlAppName: 'example-bql-app' });
const engine = await connect({
bqlAppName: 'example-bql-app',
auth: { method: 'app', appName: 'example-auth-app' },
});
// A per-call appName overrides the engine default
const result = await engine.bql("get(px_last) for('AAPL US Equity')", {
appName: 'example-call-app',
});
console.log(result);bql(query, { appName }), then raw kwargs: { 'clientContext.appName': '...' }, then bqlAppName. With none of them, BQL requests omit clientContext.appName.bqlAppName is independent of auth.appName. It does not authorize the session, set the SDK application identity, or name the session, and neither value is derived from the other.Two independent controls write to standard error:
| Control | Default | Scope |
|---|---|---|
setLogLevel(level) / getLogLevel() | 'warn' | xbbg engine log level: 'trace', 'debug', 'info', 'warn', or 'error'; process-wide and changeable at any time. A simple level in RUST_LOG sets the initial value |
sdkLogLevel in EngineConfig | 'off' | Bloomberg C++ SDK log level: 'off', 'fatal', 'error', 'warn', 'info', 'debug', or 'trace' |
import { connect, getLogLevel, setLogLevel } from '@xbbg/core';
setLogLevel('debug');
console.log(getLogLevel()); // 'debug'
const engine = await connect({ sdkLogLevel: 'info' });SDK messages are forwarded into the xbbg log at their own severity, so they also pass through setLogLevel. The SDK log hook is registered once per process, by the first engine whose sdkLogLevel is not 'off'. setLogLevel throws for an unknown level.
Choose between configure() and connect().
Per-subscription buffers, overflow, and shared feeds.
The same engine settings in snake_case for xbbg.
The generated EngineConfig declaration.