Storage Tiering: db-tracked vs db-only directories
Overview
ModusBrain supports storage tiering to separate version-controlled content from bulk machine-generated data. This prevents git repositories from becoming bloated with large amounts of automatically generated content while still preserving it in the database.Note on naming: prior to v0.22.11 the keys weregit_tracked/supabase_only. The canonical names are nowdb_tracked/db_only(engine-agnostic — works on both PGLite and Postgres). The deprecated keys still load with a once-per-process warning. Runmodusbrain doctor --fixfor an automated rename when that path lands.
Configuration
Add astorage section to your modusbrain.yml file in the brain repository root:
- Each directory must end with
/for canonical form. The validator auto-normalizes missing trailing slashes (one-time info note shows what changed). - A directory cannot appear in both tiers — that’s a tier-overlap error and
loadStorageConfigthrowsStorageConfigError. Editmodusbrain.ymlto remove the overlap and try again.
Behavior Changes
1. modusbrain sync — automatic .gitignore management
When storage configuration is present, modusbrain sync automatically manages .gitignore entries on every successful sync:
- Adds missing
db_onlydirectory patterns to.gitignore. - Idempotent — re-running adds no duplicate entries.
- Stable comment header so the managed block is grep-able.
- Skipped on
--dry-run(don’t mutate disk in preview mode). - Skipped on
blocked_by_failuresstatus (sync state is inconsistent). - Skipped when the repo is a git submodule (
.gitis a file, not a directory) — submodule .gitignore changes don’t survive parent updates. A warning explains. - Skipped entirely when
MODUSBRAIN_NO_GITIGNORE=1is set (escape hatch for shared-repo setups where a maintainer wants modusbrain to leave .gitignore alone). - Failures (write permission denied, etc.) are caught and logged, never crash sync.
.gitignore addition:
2. modusbrain export --restore-only — repopulate missing db_only files
--restore-only flag:
- Resolves repoPath via the chain
--repo→ typedsources.getDefault()→ hard error. Never falls through to the current directory. - Only exports pages that match
db_onlypatterns AND are missing from disk. - Ideal for container restart recovery and fresh clones.
3. modusbrain storage status — storage-tier health dashboard
- Total page counts by storage tier.
- Disk usage breakdown by tier.
- Missing files that need restoration (top 10 shown; full list in
--json). - Configuration validation warnings.
- Current tier directory listing.
Validation
loadStorageConfig runs normalizeAndValidateStorageConfig after parsing:
- Auto-fixes (silent, with one-time info note showing what changed):
- Missing trailing
/is added:'media/x'→'media/x/'.
- Missing trailing
- Throws
StorageConfigError(caller sees a clean exit-1 with actionable message):- Same directory in both
db_trackedanddb_only(ambiguous routing).
- Same directory in both
Use cases
Brain repository scaling
Perfect for brain repositories crossing 50K-200K+ files where:- Core knowledge (people, companies, deals) remains git-tracked.
- Bulk data (tweets, articles, transcripts) moves to db_only.
- Development stays fast with smaller git repos.
- Full data remains available via the database.
Container-based deployments
Essential for ephemeral container environments:- Git repo contains only essential files.
- Container restarts don’t lose db_only data.
modusbrain export --restore-onlyquickly restores bulk files when needed.- Local disk acts as a cache layer.
Multi-environment consistency
Enables consistent data access across environments:- Development: small git clone, restore bulk data on demand.
- Production: full dataset via the database, selective local caching.
- CI/CD: fast tests with git-tracked data only.
Migration strategy
- Assess current repository: use
modusbrain storage statusto understand current distribution. - Plan directory structure: identify which directories should be db_tracked vs db_only.
- Create
modusbrain.yml: add storage configuration to the repository root. - Test with dry-run:
modusbrain sync --dry-runto verify behavior;.gitignoreis NOT touched on dry-run. - Run a real sync:
modusbrain syncupdates.gitignoreautomatically on success. - Verify restore: test
modusbrain export --restore-only --repo .against a small db_only directory.
Best practices
- Directory naming: end storage paths with
/(canonical form). The validator normalizes if you forget. - Start small: begin with clearly machine-generated directories in
db_only. - Address validation errors: tier overlap is an error, not a warning. Fix it before sync.
- Test restore: regularly test
--restore-onlyin staging environments. - Document decisions: comment your
modusbrain.ymlto explain tier choices.
PGLite engine note
On the PGLite engine (modusbrain’s local-only embedded Postgres), the “DB” your db_only pages live in IS the local file modusbrain uses for everything else. The.gitignore housekeeping still helps (keeps bulk content out of git history), but the offload-to-DB promise is technically vacuous. A once-per-process soft-warn explains when the engine is detected. To get full tiering, migrate to Postgres with modusbrain migrate --to supabase.
Compatibility
- Backward compatible: systems without
modusbrain.ymlwork unchanged. - Progressive enhancement: add configuration when needed.
- Database unchanged: all data remains in Postgres regardless of tier.
- Existing workflows: all existing
syncandexportbehavior preserved. - Deprecated keys:
git_tracked/supabase_onlystill load with a once-per-process warning.