codingstairs
NotesEDULifeContact
⌕Search⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

Get in touch

Send without signing in. Add your email if you'd like a reply.

  • Leave a message anonymously →
  • ✉ warragon112@gmail.com
  • KakaoTalk Open Chat ↗

© 2026 codingstairs

  • Notes
  • EDU
  • Search
  • Life
  • Contact
  • Legal
  • RSS
  • GitHub
Notes›data

Keep DB seed sources outside the code tree

Published 2026-05-26·0 views

Keep DB seed sources outside the code tree

When a project ships content (Markdown, JSON, CSV…) as DB seed, where those files live is a surprisingly big decision. The obvious place — inside the app folder that consumes them (frontend/myapp/content/) — turns out to be the worst long-term home. Putting them at monorepo root is almost always right.

1. What goes wrong inside the app folder

Incident Root cause
Seed walker scans both v1 and v2 folders → duplicate inserts Migration source and SSOT cohabit
Seed files end up in the app image → larger container Bundled with app code
Editing seed triggers an app rebuild Next/Vite watch content/
docker-compose mount points into the app dir → confuses operators Blurs content ≠ code

2. Why monorepo-root placement wins

my-monorepo/
├── notes/            ← seed SSOT (monorepo root)
│   ├── backend/
│   │   ├── 01-...ko.md
│   │   └── 01-...en.md
│   └── frontend/...
├── courses/          ← seed SSOT
│   └── <series>/...
├── frontend/
│   └── admin/        ← app (seeder walks ../../notes)
└── docker-compose.yml  (../../notes:/notes:ro mount)

At root:

  • Folder structure itself enforces content ≠ code
  • docker mounts read cleanly: content = /notes, code = /app
  • Editing seed triggers zero app rebuilds
  • After v1 → v2 migration, you can simply delete the v1 folder without touching app code

3. Clean up dead paths after migration — in one shot

The most common slip when adopting this pattern is leaving the v1 folder around "just in case." If you do:

  • Seeder walks v1 + v2 → duplicates or gaps
  • New contributors can't tell which is SSOT
  • The v1 mount in docker-compose.yml becomes a stale dead mount

The right fix is in one go: git rm -rf + delete the mount line + delete helper functions + sync 5 docs. Miss any one of those five spots and the next contributor gets confused.

4. Before / after

Aspect Inside app folder At monorepo root
Content ↔ code boundary Blurry Folder-level separation
Build trigger on edit Triggered Not triggered
Container image size Includes seeds Seeds mounted at runtime
Cleanup after v1 → v2 Easy to leave behind One-shot git rm
SSOT clarity for new joiners "Which one?" Root is explicit

5. Adopting this in your own project

  • If content lives in app/content/ or src/seed/, move it to monorepo root.
  • Update the seeder to walk relative to process.cwd() + ../../.
  • Unify docker-compose mounts to the form ../../notes:/notes:ro.
  • When v1 → v2 migration is complete, delete v1 folder + mount + helper in one commit.
  • State "content SSOT = root /notes /courses" in README and folder-structure docs.

Code and content are assets with different change cadences. Things that change on different cadences should live in different folders — that's the lowest operational cost.

More in data

All in this category →
  • Supabase Storage — File Upload and Permissions
  • Kafka in Practice — Topic Design and Message Flow
  • Orchestrating multiple PostgreSQL pools
  • Backup and Restore
  • Image Pipeline
  • Push Notifications — FCM and Web Push