Configuration Reference
This page is the public reference for new MonSQLize(options). It focuses on the constructor configuration surface. Method-level options such as find(..., { cache, maxTimeMS }) are documented on the corresponding method pages.
Use this page when you want to answer:
- What is the smallest valid constructor config?
- Which fields can be set globally?
- How should MongoDB, cache, Redis, Model, sync, pools, logging, and pagination be configured together?
- Which values are defaults and which values are validated at runtime?
Minimal configuration
import MonSQLize from 'monsqlize';
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'app',
config: {
uri: 'mongodb://127.0.0.1:27017'
}
});
await msq.connect();
const users = msq.collection('users');
const list = await users.find({ status: 'active' }).toArray();
await msq.close();
type: 'mongodb' is required by the current runtime. databaseName is recommended for clarity; if omitted, the runtime falls back to database, then to default.
Production-shaped example
import MonSQLize from 'monsqlize';
import Redis from 'ioredis';
const redis = new Redis('redis://127.0.0.1:6379/0');
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'shop',
config: {
uri: 'mongodb://mongo.internal:27017/shop',
options: {
maxPoolSize: 20,
minPoolSize: 2,
serverSelectionTimeoutMS: 5000
}
},
maxTimeMS: 3000,
findLimit: 500,
findMaxLimit: 10000,
findMaxSkip: 50000,
findPageMaxLimit: 500,
slowQueryMs: 500,
cursorSecret: 'replace-with-a-stable-secret',
requireCursorSecret: true,
cache: {
memory: {
maxEntries: 100000,
defaultTtl: 60000,
enableStats: true
},
redis: {
redis,
timeoutMs: 300,
prefix: 'shop:'
},
distributed: {
redis,
channel: 'shop:cache:invalidate',
instanceId: 'api-1'
},
autoInvalidate: false
},
logger: console,
slowQueryLog: {
enabled: true,
storage: {
type: 'mongodb',
useBusinessConnection: true,
database: 'ops',
collection: 'slow_queries',
ttl: 7 * 24 * 3600
}
},
models: {
path: './models',
pattern: '*.model.{js,mjs,cjs}',
recursive: false
},
autoIndex: false,
writePathPolicy: {
default: 'allow-both'
}
});
The Redis cache adapter and distributed invalidator can share the same Redis URL. They are separate runtime concerns: L2 cache stores query results, while cache.distributed opens Pub/Sub for cross-instance invalidation.
Top-level options
Mongo connection config
config is passed to the MongoDB adapter and optional SSH/memory-server setup.
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'private_app',
config: {
uri: 'mongodb://mongo.internal:27017/private_app',
ssh: {
host: 'bastion.example.com',
port: 22,
username: 'deploy',
privateKeyPath: '~/.ssh/id_rsa'
},
remoteHost: 'mongo.internal',
remotePort: 27017
}
});
Cache config
Query caching is opt-in per query. A global cache backend only controls where cached query results are stored once a query asks for caching with cache: <ttlMs>.
Use cache: 0 on a query to disable that query's cache. Use cache: { enabled: false } when you need the constructor-level cache backend to be disabled. Do not pass a boolean as the constructor cache config.
Memory cache
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'shop',
config: { uri: 'mongodb://127.0.0.1:27017' },
cache: {
maxEntries: 100000,
maxMemory: 0,
defaultTtl: 60000,
enableStats: true,
enableTags: false,
cleanupInterval: 60000
}
});
Redis-backed cache
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'shop',
config: { uri: 'mongodb://127.0.0.1:27017' },
cache: MonSQLize.createRedisCacheAdapter('redis://127.0.0.1:6379/0')
});
For a local + Redis two-level cache, prefer the declarative memory + redis shape:
const redisUrl = 'redis://127.0.0.1:6379/0';
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'shop',
config: { uri: 'mongodb://127.0.0.1:27017' },
cache: {
memory: { maxEntries: 10000, defaultTtl: 60000 },
redis: { url: redisUrl, timeoutMs: 300, prefix: 'shop:' },
policy: {
writePolicy: 'both',
backfillLocalOnRemoteHit: true
}
}
});
Distributed invalidation
cache.distributed enables Redis Pub/Sub invalidation messages between monSQLize instances. It does not automatically infer a Pub/Sub connection from the L2 cache; configure redisUrl, url, uri, or an existing Redis-like redis instance explicitly. The same Redis instance can be used for both L2 cache and distributed invalidation.
import Redis from 'ioredis';
const redis = new Redis('redis://127.0.0.1:6379/0');
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'shop',
config: { uri: 'mongodb://127.0.0.1:27017' },
cache: {
memory: { maxEntries: 10000 },
redis: { redis },
distributed: {
redis,
channel: 'shop:cache:invalidate',
instanceId: 'api-1',
enabled: true
}
}
});
Cache invalidation is best-effort and eventually coherent across instances. MongoDB writes are not rolled back if cache invalidation or distributed publishing fails after the write.
Logger config
Pass console, null, or a logger object with all four log-level methods. Objects such as { level: 'debug' } are ignored because they do not satisfy the logger interface.
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'shop',
config: { uri: 'mongodb://127.0.0.1:27017' },
logger: {
debug: (...args) => console.debug(...args),
info: (...args) => console.info(...args),
warn: (...args) => console.warn(...args),
error: (...args) => console.error(...args)
}
});
Model and schema-dsl config
The Model layer uses an isolated schema-dsl/runtime by default. Configure schemaDsl only when you need to inject an existing runtime, register extensions, pass runtime options, or disable schema-dsl validation.
import { createRuntime } from 'schema-dsl/runtime';
const schemaRuntime = createRuntime({
messages: {
required: 'Required field'
}
});
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'shop',
config: { uri: 'mongodb://127.0.0.1:27017' },
schemaDsl: {
runtime: schemaRuntime
}
});
Automatic index creation preflights declared indexes, skips existing indexes, and creates only missing indexes. It does not drop, rename, or rebuild conflicting indexes; use ensureIndexes({ dryRun: true }) or ensureModelIndexes({ dryRun: true }) as an explicit production release gate before changing production indexes.
Namespace config
Use namespace when several monSQLize instances share one cache backend and their cache keys must remain isolated.
Write path policy
By default, both collection and Model writes are available. Use model-only when selected namespaces must pass through Model hooks, defaults, timestamps, versioning, and soft-delete behavior.
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'shop',
config: { uri: 'mongodb://127.0.0.1:27017' },
writePathPolicy: {
default: 'model-only',
namespaces: {
'shop.audit_logs': 'allow-both'
}
}
});
See Write Path Policy.
Pool config
Configure pools in the constructor when your service needs named database connections.
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'main',
config: { uri: 'mongodb://primary:27017/main' },
pools: [
{
name: 'analytics',
uri: 'mongodb://analytics:27017/main',
role: 'analytics',
tags: ['reporting'],
options: { maxPoolSize: 5 }
}
],
poolStrategy: 'auto',
poolFallback: { enabled: true, fallbackStrategy: 'primary' },
maxPoolsCount: 5
});
const reports = msq.pool('analytics').collection('reports');
See Pool Configuration.
Sync config
sync wires a Change Stream fan-out manager. The runtime provides at-least-once delivery; targets should be idempotent. Use sync.idempotency to reduce duplicate target side effects.
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'main',
config: { uri: 'mongodb://primary:27017/main?replicaSet=rs0' },
sync: {
enabled: true,
collections: ['orders'],
targets: [
{
name: 'backup',
uri: 'mongodb://backup:27017',
databaseName: 'backup',
collections: ['orders']
}
],
resumeToken: {
storage: 'file',
path: './.sync-resume-token',
strictLoad: true,
strictSave: true,
saveRetries: 2,
saveRetryDelayMs: 100
},
idempotency: {
enabled: true,
keyPrefix: 'monsqlize:sync:idempotency',
ttl: 24 * 3600 * 1000,
markMode: 'success'
}
}
});
See Change Stream Sync.
Slow query logging
Use slowQueryMs for the runtime threshold and slowQueryLog when you want persistent aggregation of slow-query records.
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'shop',
config: { uri: 'mongodb://127.0.0.1:27017' },
slowQueryMs: 500,
log: {
slowQueryTag: { event: 'slow_query', code: 'SLOW_QUERY' },
formatSlowQuery: (meta) => meta
},
slowQueryLog: {
enabled: true,
storage: {
type: 'mongodb',
useBusinessConnection: true,
database: 'ops',
collection: 'slow_queries',
ttl: 7 * 24 * 3600
},
filter: {
minExecutionTimeMs: 1000,
excludeCollections: ['healthchecks']
}
}
});
See Slow Query Logging.
Transaction config
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'shop',
config: { uri: 'mongodb://127.0.0.1:27017/shop?replicaSet=rs0' },
transaction: {
enableRetry: true,
maxRetries: 3,
retryDelay: 100,
retryBackoff: 2,
defaultTimeout: 30000,
lockMaxDuration: 30000,
lockCleanupInterval: 60000
}
});
Transaction cache locks are process-local. For cross-instance critical sections, use application-level idempotency/fencing or an explicit business lock.
Count queue config
countQueue is a process-local cooperative queue for count-heavy paths such as paginated totals.
Runtime validation
These constructor options are validated when the instance is created:
findLimit must also be less than or equal to findMaxLimit.
Configuration priority
For options that exist at both instance and method level, method-level options win.
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'shop',
config: { uri: 'mongodb://127.0.0.1:27017' },
maxTimeMS: 3000
});
await msq.connect();
const users = msq.collection('users');
await users.find({}, { maxTimeMS: 5000 }); // Uses 5000.
await users.find({}); // Uses 3000.
Common mistakes
Related pages