# Seeding: scripts, not migrations, and idempotent
Seed data (demo orgs, test users, reference rows) is not schema. In a migration it runs once per environment and can never be safely rerun; by hand it is unrepeatable. A seed script runs whenever you need it and converges to the same state.
## Checkable procedure
1. Write seed scripts with upserts keyed on natural keys (email, slug), not bare inserts. Running the seed twice must produce the same database, not duplicate rows.
2. Keep seeds out of the migrations directory. Migrations change schema and run once; seeds populate data and run on demand. Mixing them breaks `db reset` semantics.
3. Version seeds with the code that needs them. When the app starts requiring a new reference row, the seed change ships in the same PR.
4. Separate demo seeds from test fixtures. Demo seeds are for humans clicking around; test fixtures are minimal and deterministic for CI. One script serving both does neither well.
5. Never seed production with test users. Production seeds are limited to reference data (plans, regions, feature flags), applied deliberately, and reviewed like a migration.
## Ordering constraints
Schema migrations first, then seeds. CI runs migrations then test fixtures then the suite. Local `db reset` ends with seeds so the dev database is immediately usable.
## Verification
Run the seed twice against a fresh database and diff: identical state, no duplicates. Reset and reseed, then run the test suite green.