# Journal — 2026-04-08 ## 2026-04-08 — Per-Document Subdirectory Versioning Addressed a scalability issue with the version storage layout. All version files for documents in a directory were stored in a single flat `versions/` directory, which degrades with thousands of files due to `findVersions` doing a full `ReadDir` and filtering by prefix. ### What Changed Moved from flat layout (`versions/doc.md.v1`) to per-document subdirectories (`versions/doc.md/v1`). This scopes `findVersions` to only that document's versions instead of scanning all entries. Key design decisions: - **Lazy migration**: old-layout documents migrate to per-doc on next write. Reads support both layouts transparently. Zero-downtime upgrade. - **No client changes needed**: the publish CLI (`demarkus-publish`) writes directly via `Store.Write`, so it picks up migration automatically. Network clients are unaffected since this is server-side storage only. - **`resolveVersionFile` for reads**: tries per-doc first, falls back to flat. Handles partially-migrated stores where individual versions may be in either layout. - **Write-path always per-doc**: `newVersionFilePath` and `newVersionSymlinkTarget` have no layout parameter. ### Code Review Fixes A go-reviewer audit caught several issues that were fixed in a second pass: - **Eliminated `perDoc bool` parameter leak**: replaced with `resolveVersionFile` (reads) and `newVersionFilePath` (writes) so callers never need to know the layout - **Fixed partial-migration bug**: `VerifyChain`, `getVersion`, and `Archive` previously snapshot the layout once and used it for all versions. Now each version resolves independently. - **Fixed silent error swallowing**: `isCurrentArchived` now returns `(bool, error)` instead of silently returning false on read failures. `prepareExistingDoc` surfaces non-ErrNotExist read errors. - **Extracted `prepareExistingDoc`** from `Write` to stay under cyclomatic complexity lint threshold. All backward-compat code marked with `TODO(v1)` for removal at v1 release. Subdirectory tests added for deep nesting and migration in nested paths. ## Related documents - [Versions sharding plan](/plans/versions-sharding.md): the per-document version layout implemented here