Skip to content

Bug: usageDb and requestDetailsDb ignore DATA_DIR — usage data lost on Docker restart #138

@Wladefant

Description

@Wladefant

Problem

When running 9router in Docker with DATA_DIR=/app/data and a persistent volume mounted at /app/data, all usage data, request logs, and request detail recordings are lost whenever the Docker container is restarted (e.g. VPS crash, Docker daemon restart, redeployment).

This happens because usageDb.js and requestDetailsDb.js use os.homedir() (resolving to ~/.9router/) to store their data files, while localDb.js correctly respects the DATA_DIR environment variable.

Affected Files and Storage Paths

Module File Storage Path Respects DATA_DIR?
src/lib/localDb.js db.json ${DATA_DIR}/db.json Yes
src/lib/usageDb.js usage.json ~/.9router/usage.json No
src/lib/usageDb.js log.txt ~/.9router/log.txt No
src/lib/requestDetailsDb.js request-details.sqlite ~/.9router/request-details.sqlite No

This is already noted in docs/ARCHITECTURE.md:

"usageDb currently stores under ~/.9router and does not follow DATA_DIR."

Steps to Reproduce

  1. Deploy 9router with Docker, set DATA_DIR=/app/data, mount a persistent volume at /app/data
  2. Use the proxy, accumulate usage data and request logs
  3. Restart the Docker container (e.g. docker restart)
  4. All usage stats, cost tracking, request logs, and request detail recordings are gone
  5. Config/settings in db.json are preserved (because localDb.js correctly uses DATA_DIR)

Current Workaround

Mount an additional volume at /root/.9router to persist the usage data directory. This works but requires users to know about this undocumented second data location.

Suggested Fixes

Option A: Make usageDb and requestDetailsDb respect DATA_DIR (Recommended)

In both src/lib/usageDb.js and src/lib/requestDetailsDb.js, change the DATA_DIR resolution to check for the DATA_DIR env variable first, falling back to the current getUserDataDir() logic:

// Before (current):
const DATA_DIR = getUserDataDir();

// After (proposed):
const DATA_DIR = process.env.DATA_DIR || getUserDataDir();

This is a one-line change in each file and would make all data files land in the same directory (/app/data/) when DATA_DIR is set, requiring only a single volume mount for full persistence.

Option B: Document the second volume mount requirement

If changing the storage behavior is not desired, the Dockerfile and README should document that Docker deployments need two volume mounts:

  • /app/data for config/state (db.json)
  • /root/.9router for usage data (usage.json, log.txt, request-details.sqlite)

Option C: Update the Dockerfile

Add a VOLUME instruction for both paths in the Dockerfile:

VOLUME ["/app/data", "/root/.9router"]

Environment

  • 9router version: latest (master)
  • Deployment: Docker via Dokploy
  • OS: Linux (node:20-alpine)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions