Salut,
Je ne sais pas si je suis le seul, mais j’ai des erreurs de OOM régulièrement, lorsque j’attribue 8Gb a Gladys. Cela provoque un redémarrage de Gladys toute les nuits.
Après des jours de débug, sans comprendre la cause, j’ai utilisé Claude pour avancer et identifier une meilleure hypothèse. Et les jours suivants le problème est identifié : la manière dont la base de données est sauvegardée.
Contexte : je garde tous les états a l’infini, tant que j’ai du disque.
Est ce que je suis le seul a qui ça arrive ?
Bug : le backup Gateway peut provoquer un OOM-kill du process Node
Composants concernés :
server/lib/gateway/gateway.backup.js
server/models/index.js (fonction duckDbCreateBackupInstance)
Le problème : duckDbCreateBackupInstance() ouvre une nouvelle instance DuckDB séparée sur le même fichier .duckdb que l’instance principale (déjà active en lecture/écriture) :
const backupDatabase = await DuckDBInstance.create(duckDbFilePath, {
memory_limit: duckDbMemoryLimit,
access_mode: 'READ_ONLY',
});
Or la documentation officielle du client Node.js « Neo » de DuckDB dit explicitement :
« Multiple instances in the same process should not attach the same database. »
Le mécanisme prévu pour éviter ça est DuckDBInstanceCache.getOrCreateInstance(path), qui réutilise la même instance (donc le même buffer pool / memory_limit) pour un même fichier. Le code actuel appelle DuckDBInstance.create() directement, ce qui crée deux buffer pools indépendants, chacun plafonné au même DUCKDB_MEMORY_LIMIT.
Résultat : le pire cas mémoire de DuckDB seul devient 2 × memory_limit au lieu de 1 × memory_limit.
Aggravant : la doc DuckDB précise aussi que memory_limit « only applies to the buffer manager » — les buffers de compression (COMPRESSION GZIP utilisé dans l’EXPORT DATABASE) peuvent consommer en plus de cette limite.
Preuve en prod (2 crashs identiques, logs à l’appui) :
- RSS stable ~2,5 Go avant backup (dont ~1,2 Go de BASE_TABLE DuckDB)
- Passage à ~4,6 Go en moins d’une minute, juste après le log « Backing up DuckDB into a Parquet folder »
- Process tué (ExitCode=137) avant d’atteindre le log « Closing DuckDB backup instance to release memory » dans le finally — donc le crash survient bien pendant l’appel EXPORT DATABASE … FORMAT PARQUET COMPRESSION GZIP lui-même, pas après.
- Reproduit à l’identique 2 jours de suite, toujours au moment du backup Gateway quotidien.
Ce qui est demandé :
- Faire en sorte que duckDbCreateBackupInstance() utilise DuckDBInstanceCache.getOrCreateInstance() au lieu de DuckDBInstance.create(), pour que le backup partage le buffer pool de l’instance principale plutôt que d’en ouvrir un second.
- Envisager de remplacer COMPRESSION GZIP par ZSTD ou SNAPPY dans l’EXPORT DATABASE (moins de buffers de compression, export plus rapide).
- Éventuellement documenter que DUCKDB_MEMORY_LIMIT doit être dimensionné en anticipant que deux instances peuvent coexister pendant un backup (donc recommander une valeur ≤ 25% de la RAM allouée au conteneur, pas 30-50%), tant que le point 1 n’est pas corrigé.
Contexte pour situer l’impact : installation avec ~8 Go alloués au conteneur, BASE_TABLE d’environ 1,1-1,2 Go d’historique de capteurs — donc pas un cas extrême, ce comportement peut probablement toucher d’autres installations avec un historique conséquent.


