diff --git a/apps/server/src/core/base/query-cache/query-cache.config.ts b/apps/server/src/core/base/query-cache/query-cache.config.ts index 4b4fcdf1..ffc78ac8 100644 --- a/apps/server/src/core/base/query-cache/query-cache.config.ts +++ b/apps/server/src/core/base/query-cache/query-cache.config.ts @@ -6,6 +6,8 @@ export type QueryCacheConfig = { minRows: number; maxCollections: number; warmTopN: number; + memoryLimit: string; + threads: number; }; @Injectable() @@ -17,6 +19,8 @@ export class QueryCacheConfigProvider { minRows: env.getBaseQueryCacheMinRows(), maxCollections: env.getBaseQueryCacheMaxCollections(), warmTopN: env.getBaseQueryCacheWarmTopN(), + memoryLimit: env.getBaseQueryCacheMemoryLimit(), + threads: env.getBaseQueryCacheThreads(), }; } } diff --git a/apps/server/src/integrations/environment/environment.service.ts b/apps/server/src/integrations/environment/environment.service.ts index 4dceff20..a53dbb7f 100644 --- a/apps/server/src/integrations/environment/environment.service.ts +++ b/apps/server/src/integrations/environment/environment.service.ts @@ -343,4 +343,23 @@ export class EnvironmentService { .toLowerCase() === 'true' ); } + + getBaseQueryCacheMemoryLimit(): string { + // Per-DuckDB-instance memory ceiling. DuckDB accepts human-readable sizes: + // '32MB', '128MB', '1GB'. Default keeps a single instance from + // monopolising the heap if a runaway query needs to spill. + return this.configService.get( + 'BASE_QUERY_CACHE_MEMORY_LIMIT', + '64MB', + ); + } + + getBaseQueryCacheThreads(): number { + // Per-DuckDB-instance thread budget. Defaults to 2 so multiple concurrent + // instances don't fight for every core on a shared host. + return parseInt( + this.configService.get('BASE_QUERY_CACHE_THREADS', '2'), + 10, + ); + } }