피드로 돌아가기
How I tracked down a 36GB memory leak in a Claude Code memory server
Dev.toDev.to
Backend

sql.js MEMFS 누수로 인한 36GB RSS 메모리 릭 해결

How I tracked down a 36GB memory leak in a Claude Code memory server

Ivan Maksimov2026년 6월 22일6advanced

Context

Node.js 기반의 MCP 서버가 sql.js를 통해 SQLite 데이터를 처리하는 구조임. 매 요청마다 Database 인스턴스를 새로 생성하며 WASM 메모리 상의 가상 파일 시스템(MEMFS)에 데이터베이스 이미지를 반복적으로 적재하는 설계적 결함이 존재함.

Technical Solution

  • Heap Profiler 분석을 통해 V8 heapTotal은 일정하나 external/arrayBuffers가 급증하는 Native Memory leak 패턴 식별
  • Retainer Chain 추적으로 JSArrayBufferData가 Emscripten MEMFS의 dbfile_* 노드들에 의해 점유되고 있음을 발견
  • JS Wrapper 객체는 GC 대상이나 내부 WASM 메모리는 explicit close() 호출 전까지 해제되지 않는 특성 파악
  • 임시 조치로 /proc//status 기반의 RSS Watchdog을 구현하여 임계치 초과 시 프로세스 Graceful Respawn 수행
  • 근본 해결을 위해 Database 인스턴스를 경로별로 캐싱하는 Singleton 패턴을 도입하여 불필요한 DB 중복 로드 제거
  • SQLite WAL 모드의 특성을 반영하여 .db, -wal, -shm 파일 전체를 관리하는 백업 전략 수립

1. RSS 증가 시 heapTotal과 external/arrayBuffers 수치를 대조하여 Native Leak 여부 확인

2. --max-old-space-size 설정이 Native Memory 영역에는 영향을 주지 않음을 인지

3. WASM 기반 라이브러리 사용 시 내부 가상 파일 시스템(MEMFS)의 생성/삭제 생명주기 검토

4. SQLite WAL 모드 백업 시 3개 파일(.db, -wal, -shm)의 정합성 유지 확인

원문 읽기