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

OptionTypeDefaultDescription
type'mongodb'noneRequired by the current runtime.
databaseNamestring'default' after alias fallbackDefault database name.
databasestringnoneAlias that takes priority over databaseName.
configMongoConnectConfignoneMongoDB connection config.
cacheMemoryCache, CacheLike, MultiLevelCacheOptions, or plain cache configmemory cacheRuntime query-cache backend.
cache.autoInvalidatebooleanfalseBroadly invalidate collection read caches after successful monSQLize writes; disabled by default.
loggerLoggerLike | nullnullCustom logger. Must expose debug, info, warn, and error.
schemaDslfalse | SchemaDslRuntimeConfigisolated runtimeModel schema-dsl runtime integration.
modelsstring | { path, pattern?, recursive? }noneAuto-load Model definition files on connect.
autoIndexboolean | objecttrueControls automatic Model index creation.
writePathPolicyWritePathPolicyOptionsallow-bothOptional policy for collection-vs-Model writes.
poolsPoolConfig[]noneAdditional MongoDB connection pools.
poolStrategyPoolStrategymanager defaultPool selection strategy.
poolFallbackboolean | objectmanager defaultPool fallback behavior.
maxPoolsCountnumbermanager defaultMaximum number of configured pools.
transactionobjectmanager defaultsGlobal transaction defaults and statistics settings.
syncSyncConfigdisabledChange Stream fan-out sync configuration.
slowQueryLogboolean | Partial<SlowQueryLogConfig>disabledPersistent slow-query log storage.
maxTimeMSnumber2000Global query timeout in milliseconds.
findLimitnumber500Default find() limit when the caller does not set one.
findMaxLimitnumber10000Maximum explicit find().limit(n) value. limit(0) keeps MongoDB unlimited semantics.
findMaxSkipnumber50000Maximum explicit find().skip(n) and offsetJump.maxSkip.
findPageMaxLimitnumber500Maximum findPage() limit. Requests above this cap are clamped.
slowQueryMsnumber500Threshold used by slow-query detection and slow-query log defaults.
namespace{ scope?, instanceId? }{ scope: 'database' }Cache namespace isolation.
cursorSecretstringnoneHMAC secret for findPage() cursor tokens.
requireCursorSecretbooleanfalseReject findPage() until cursorSecret is configured.
cursorSecretWarning'off' | 'production' | 'always''production'Controls startup warning when cursorSecret is missing.
cursorTypesRecord<string, CursorValueType>noneField type hints for decoded cursor values.
cursorValueNormalizerCursorValueNormalizernoneCustom decoded cursor value normalizer.
log.slowQueryTag{ event?, code? }{ event: 'slow_query', code: 'SLOW_QUERY' }Slow-query event tag fields.
log.formatSlowQuery(meta) => unknownnoneCustom formatter for slow-query event metadata.
autoConvertObjectIdboolean | object | field maptrue for MongoDBAuto-convert valid 24-character hex strings to ObjectId.
countQueueboolean | objectenabledBatches count operations under concurrency pressure.

Mongo connection config

config is passed to the MongoDB adapter and optional SSH/memory-server setup.

OptionTypeDescription
config.uristringMongoDB connection URI. Required unless useMemoryServer is true.
config.optionsMongoClientOptionsDriver options such as maxPoolSize, serverSelectionTimeoutMS, and read/write concerns.
config.readPreferenceMongoDB read preferenceShortcut merged into MongoDB client options.
config.useMemoryServerbooleanStarts mongodb-memory-server automatically for tests.
config.memoryServerOptionsobjectMemory-server instance and binary options.
config.sshSSHConfigBastion tunnel config.
config.remoteHost / config.remotePortstring / numberRemote MongoDB host and port visible from the SSH server.
config.mongoHost / config.mongoPortstring / numberAliases for remoteHost / remotePort.
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
  }
});
OptionDescription
cache.maxEntriesMaximum entry count.
cache.maxMemoryMaximum memory in bytes. 0 means unlimited.
cache.defaultTtlDefault TTL in milliseconds when a set operation does not pass TTL.
cache.enableStatsEnables hit/miss/eviction stats.
cache.enableTagsEnables tag-based invalidation when the cache backend supports it.
cache.cleanupIntervalPeriodic TTL cleanup interval in milliseconds.
cache.enabledSet to false to disable this cache backend.

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.

cache.distributed optionTypeDefaultDescription
enabledbooleantrue when the block is presentSet to false to keep the object shape while disabling Pub/Sub.
redisRedis-like instancenoneExisting Redis client used for publish/subscribe. Can be the same instance as the L2 cache.
redisUrlstringnoneRedis URL used when monSQLize creates the Pub/Sub client.
url / uristringnoneAliases for redisUrl.
channelstringmonsqlize:cache:invalidatePub/Sub channel shared by all instances that should receive invalidation messages.
instanceIdstringgenerated valueInstance identifier used to ignore messages published by the same runtime.

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
  }
});
OptionTypeDefaultDescription
schemaDslfalse | objectisolated runtimeOmit it for the default isolated runtime; set to false only when Model schema validation is intentionally disabled.
schemaDsl.enabledbooleantrueSet to false to disable validation while keeping the object shape.
schemaDsl.runtimeschema-dsl runtimenoneExisting runtime. monSQLize uses it but does not dispose it on close().
schemaDsl.optionsSchemaDslRuntimeOptionsnoneOptions passed when monSQLize creates the runtime.
schemaDsl.extensionsunknown[]noneExtension definitions registered before Model schema compilation.
modelsstring | objectnoneFile path or { path, pattern, recursive } for auto-loading Model definitions.
autoIndexboolean | objecttrueGlobal automatic Model index creation control. Model-level options.autoIndex overrides this value.
autoIndex formEffect
trueSchedule declared Model indexes when the Model instance is created. The task preflights with listIndexes() before creating missing indexes.
falseDo not schedule automatic Model index creation. You can still call ensureIndexes() explicitly.
{ enabled: boolean }Object form for toggling automatic index creation.
{ emitEvents: boolean }Emits model-index-error when automatic index creation fails or conflicts are detected.

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.

OptionTypeDefaultDescription
namespace.scope'database' | 'connection''database'Controls the namespace boundary used by runtime cache keys.
namespace.instanceIdstringnonePrefixes query-cache keys and invalidation patterns for one runtime instance. Use this when multiple apps share the same Redis/cache backend.

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.

transaction optionTypeDefaultDescription
enableRetrybooleanmanager defaultEnables transaction retry for retryable failures.
maxRetriesnumbermanager defaultMaximum retry attempts.
retryDelaynumbermanager defaultInitial retry delay in milliseconds.
retryBackoffnumbermanager defaultBackoff multiplier between retries.
defaultTimeout / maxDurationnumbermanager defaultTransaction timeout in milliseconds.
defaultReadConcernMongoDB read concernnoneDefault read concern passed to transaction options.
defaultWriteConcernMongoDB write concernnoneDefault write concern passed to transaction options.
defaultReadPreferenceMongoDB read preferencenoneDefault read preference passed to transaction options.
lockMaxDurationnumber30000 in the cache-lock managerProcess-local transaction cache-lock duration in milliseconds.
lockCleanupIntervalnumber60000 in the cache-lock managerProcess-local cache-lock cleanup interval in milliseconds.
maxStatsSamplesnumbermanager defaultMaximum retained transaction statistics samples.
distributedLockobjectnoneCompatibility placeholder. It does not enable distributed transaction cache locks in the current v3 runtime.

Count queue config

countQueue is a process-local cooperative queue for count-heavy paths such as paginated totals.

OptionTypeDefaultDescription
countQueueboolean | objectenabledSet to false to bypass the queue. true uses defaults.
countQueue.enabledbooleantrueEnables the queue when using object form.
countQueue.concurrencynumberimplementation defaultMaximum concurrent count runners in this process.
countQueue.maxQueueSizenumberimplementation defaultMaximum pending count jobs before new jobs are rejected.
countQueue.timeoutnumberimplementation defaultQueue wait timeout in milliseconds. It does not forcibly cancel an already running MongoDB operation.

Runtime validation

These constructor options are validated when the instance is created:

OptionMinimumMaximum
maxTimeMS1300000
findLimit110000
findMaxLimit1100000
findMaxSkip010000000
findPageMaxLimit110000

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

MistakeUse instead
Passing a boolean as constructor cache configcache: { enabled: false } or query-level { cache: 0 }
Selecting Redis through a cache type string and host/port objectMonSQLize.createRedisCacheAdapter(redisUrl) or cache.redis.url
Passing only a logger levellogger: console or a logger with debug/info/warn/error
Relying on the L2 cache field to create Pub/SubAdd cache.distributed.redisUrl, or pass the same instance as cache.distributed.redis
Omitting typeSet type: 'mongodb'