layercache가 무엇인가요?

Node.js에서 Memory → Redis → Disk를 하나의 API로 묶어주는 멀티레이어 캐시 라이브러리입니다.

캐시 히트 시에는 가장 빠른 레이어에서 값을 꺼내고 상위 레이어를 자동으로 채웁니다. 미스 시에는 동시 요청이 100개 들어와도 fetcher는 딱 한 번만 실행됩니다.

왜 만들었나요?

Node.js 서비스를 운영하다 보면 캐싱 레이어를 쌓는 방식은 대체로 비슷한 수순을 밟습니다. 인메모리 캐시로 시작하고, 인스턴스가 늘어나면 Redis를 붙이고, 그러다 stampede 문제를 만나고, 인스턴스 간 캐시 불일치가 생기고... 각각은 해결할 수 있는 문제인데, 이걸 프로덕션 수준으로 한꺼번에 엮는 게 생각보다 손이 많이 갔습니다.

그래서 그 작업을 한 번만 제대로 해두자는 생각으로 만들었습니다.

주요 기능은 어떻게 되나요?

핵심 동작

  • 레이어드 읽기 + 자동 backfill (L1 미스 → L2 조회 → L1 채움)
  • Stampede prevention: 동시 요청 100개 → fetcher 실행 1회
  • Distributed single-flight: Redis 분산 락으로 인스턴스 간 중복 실행 제거
  • Redis pub/sub 기반 L1 invalidation bus (인스턴스 간 메모리 캐시 동기화)

무효화 / 신선도

  • 태그 기반 무효화, 와일드카드/접두어 무효화
  • Stale-while-revalidate, Stale-if-error
  • Sliding TTL, Adaptive TTL, Refresh-ahead

복원력

  • Graceful degradation: Redis 장애 시 레이어 스킵 후 자동 복구
  • Circuit breaker
  • Strict / best-effort 쓰기 정책

관측성

  • Prometheus exporter, OpenTelemetry 훅
  • 레이어별 지연 시간 측정, 이벤트 훅
  • Admin CLI (npx layercache stats|keys|invalidate)

프레임워크 통합
Express, Fastify, Hono, tRPC, GraphQL, Next.js

벤치마크 숫자가 궁금합니다

단일 코어 VM + 실제 Docker Redis 기준입니다.

| 시나리오 | 평균 지연 |
| L1 메모리 웜 히트 | 0.005 ms |
| L2 Redis 웜 히트 (1 KiB) | 0.193 ms |
| 캐시 없음 (DB 시뮬) | 5.030 ms |

  • HTTP 처리량: /layered 16,211 req/s vs /nocache 158 req/s
  • Stampede: 동시 75 요청 → origin fetch 5회 (캐시 없이는 375회)
  • Distributed single-flight: 동시 60 요청 → origin fetch 1회

전체 벤치마크 방법론과 raw 결과는 docs/benchmarking.md에 정리해두었습니다.

기존 라이브러리와는 뭐가 다른가요?

node-cache-manager, keyv, cacheable 모두 좋은 선택지입니다. 차이점을 간단히 정리하면:

  • Stampede prevention / Distributed single-flight: 세 라이브러리 모두 기본 제공하지 않습니다. layercache는 이 두 가지를 핵심으로 설계했습니다.
  • Cross-instance L1 invalidation: Redis pub/sub으로 인스턴스 간 메모리 캐시를 자동으로 동기화합니다. 멀티 인스턴스 환경에서 메모리 캐시를 안심하고 쓸 수 있습니다.
  • Auto backfill: 하위 레이어 히트 시 상위 레이어를 자동으로 채웁니다.
  • Graceful degradation + Circuit breaker: Redis가 죽어도 서비스가 살아있습니다.

설치 및 링크

npm install layercache  

설계 결정, 특히 single-flight 조율 방식이나 graceful degradation 동작에 대해 궁금하신 점 있으시면 편하게 질문해주세요.